7 ms·
What a fascinating license. This is a particularly compelling line from it: 3. You must not distribute the modified file with the filename of the origi
by whartung 4y ago
What a fascinating license.
This is a particularly compelling line from it:
3. You must not distribute the modified file with the filename of the
original file.
Just in isolation, outside of the other aspects of the license, this is pretty much completely crippling for a Java program.
Simply, if you change a file, you can't use the same name. Well, in Java, the name of the file is the name of the class. You can't have the file name differ from the class inside.
That means you can't change a Java file in this codebase.
Fascinating.
- ebruchez 4y agoAs a workaround, you could distribute the modified Foo.java as Foo2.java, and have your build system rename Foo2.java to Foo.java at build time. It might be all it takes (but IANAL).
- mqus 4y agoWHich would completely cripple IDEs or at the very least makes it difficult to work with
- KRAKRISMOTT 4y agoOr just use a shading tool (which comes by default with most Maven/Gradle builds). It is not a barrier for any experienced java developer.
- dcminter 4y agoHuh? Refactor the class name in virtually any Java supporting IDE and the file name and invocations will be changed along with it. The license term seems petty, and would be annoying, but the workaround is trivial.
- whartung 4y agoIf you do that, you have to rename every class file it impacts as well, because now those files are changed. A lot of refactoring systems don't take into account the ancillary files (like build files, start scripts, etc.). So, the workaround can be quite impactful in the end. Renaming the entirety of the code base, potentially.
- dcminter 4y agoOh, duh, now I get it. That's very annoying.
- layer8 4y agoIn principle, you could rename the classes on the class-file level after compilation, back to the original names. That wouldn’t violate the license. Moreover, under the following definition in the license: `Modification' of a file means any procedure that produces a derivative file under any applicable law -- that is, a file containing the original file or a significant portion of it, either verbatim or with modifications and/or translated into another language. …compilation would count as modification (“translated into another language”), and compilation also changes the file name (from .java to .class), so distributing the compilation output should be fine. Furthermore, any changes to the sources can be distributed as a diff patch, which also has a different file name.
- thangalin 4y ago> but the workaround is trivial. If you have a trivial solution to rename hundreds of Java classes and their references en masse without breaking the build and without renaming each file one-at-a-time, do tell. You can find more details about potential solutions I've tried here: https://stackoverflow.com/questions/75154524/bulk-rename-of-java-classes/ https://stackoverflow.com/questions/75154524/bulk-rename-of-... FYI, the following plug-in for IDEA supports regular expressions (as of Jan 20, 2023), so it may be a viable solution: https://plugins.jetbrains.com/plugin/17455-rename-files-refactor-batch https://plugins.jetbrains.com/plugin/17455-rename-files-refa...
- counttheforks 4y agoPosted a solution on your other comment: https://news.ycombinator.com/item?id=34493760 https://news.ycombinator.com/item?id=34493760
- playingalong 4y agoI bet Open Rewrite can handle that quite easily: https://docs.openrewrite.org/ https://docs.openrewrite.org/
- thangalin 4y agoI wasn't able to find a recipe that performs a regular expression rename. That is, there doesn't seem to be anything like: --- type: specs.openrewrite.org/v1beta/recipe name: com.yourorg.ChangeTypeExample displayName: Change type example recipeList: - org.openrewrite.java.ChangeType: oldFullyQualifiedTypeName: (.+) newFullyQualifiedTypeName: Kt$1
- Someone 4y agoI would do that the hacker way: - build the current TeX.jar - jar tf TeX.jar | grep whatever to get a list of to-be-renamed classes - use sed or manual editing to generate a large list of recipes - run those recipes Instead of jar tf, grep for “^package foo.bar.baz” and “class (complex regex)” in the source code to get a list of package and class names, or use the directory structure. Maybe do all of them, and compare the results for robustness. That list will be large and it may not go perfect in one go, but it’s a one-off job, and you‘ll get there.
- bedatadriven 4y agoLooks like it was inherited from an upstream project that has a long history: https://github.com/jamespfennell/new-typesetting-system#license-and-changelog https://github.com/jamespfennell/new-typesetting-system#lice...
- thangalin 4y agoI've been looking high-and-low for a way to rename Java classes en masse without breaking the build. https://stackoverflow.com/questions/75154524/bulk-rename-of-java-classes/ https://stackoverflow.com/questions/75154524/bulk-rename-of-... A number of classes have been renamed to have the Kt prefix. There are other changes that don't yet have the new prefix applied because changing those classes would ripple into, essentially, the entire code base. Hence the search for a mass rename procedure that works. Suggestions welcome. Donald Knuth set that rule up so that "plain.tex" would be the same, world-wide. I don't know why the authors applied the same license to the entire Java application, rather than limit it to Knuth's work. I've also added a comment "// Originally" that indicates the original name of the class, rather than the name of the file. This minor license violation keeps its spirit if not its letter. Otherwise there'd be no way to extract an inner class.
- counttheforks 4y agoIf you're fine using intellij then you can probably use its scripting to do this. It has access to most of the same API as plugins and can access intellij features such as its refactor rename. The (meager) docs on scripting: https://www.jetbrains.com/help/idea/ide-scripting-console.html https://www.jetbrains.com/help/idea/ide-scripting-console.ht.... The plugin docs & intellij source code (especially the unit tests) are a better source of information. And here's a script that will use intellij's refactoring to rename all classes recursively in a directory to add the prefix Renamed, correctly dealing with references & renaming files if necessary: @file:Suppress("NAME_SHADOWING") import com.intellij.notification.Notification import com.intellij.notification.NotificationType import com.intellij.notification.Notifications import com.intellij.openapi.actionSystem.* import com.intellij.openapi.keymap.KeymapManager import com.intellij.openapi.command.WriteCommandAction import com.intellij.psi.* import com.intellij.psi.search.* import com.intellij.refactoring.rename.RenameProcessor import com.intellij.util.ThrowableConsumer import java.io.PrintWriter import java.io.StringWriter import javax.swing.KeyStroke // Usage: In IDEA: Tools -> IDE Scripting Console -> Kotlin // Ctrl+A, Ctrl+Enter to run the script // Select folder containing target classes, Ctrl+Shift+A to open action menu, search for Bulk refactor //<editor-fold desc="Boilerplate"> val b = bindings as Map<*, *> val IDE = b["IDE"] as com.intellij.ide.script.IDE fun registerAction( name: String, keyBind: String? = null, consumer: ThrowableConsumer<AnActionEvent, Throwable> ) { registerAction(name, keyBind, object : AnAction() { override fun actionPerformed(event: AnActionEvent) { try { consumer.consume(event); } catch (t: Throwable) { val sw = StringWriter() t.printStackTrace(PrintWriter(sw)) log("Exception in action $name: $t\n\n\n$sw", NotificationType.ERROR) throw t } } }); } fun registerAction(name: String, keyBind: String? = null, action: AnAction) { action.templatePresentation.text = name; action.templatePresentation.description = name; KeymapManager.getInstance().activeKeymap.removeAllActionShortcuts(name); ActionManager.getInstance().unregisterAction(name); ActionManager.getInstance().registerAction(name, action); if (keyBind != null) { KeymapManager.getInstance().activeKeymap.addShortcut( name, KeyboardShortcut(KeyStroke.getKeyStroke(keyBind), null) ); } } fun log(msg: String, notificationType: NotificationType = NotificationType.INFORMATION) { log("Scripted Action", msg, notificationType) } fun log( title: String, msg: String, notificationType: NotificationType = NotificationType.INFORMATION ) { Notifications.Bus.notify( Notification( "scriptedAction", title, msg, notificationType ) ) } //</editor-fold> registerAction("Bulk refactor") lambda@{ event -> val project = event.project ?: return@lambda; val psiElement = event.getData(LangDataKeys.PSI_ELEMENT) ?: return@lambda log("Bulk refactor for: $psiElement") WriteCommandAction.writeCommandAction(event.project).withGlobalUndo().run<Throwable> { psiElement.accept(object : PsiRecursiveElementWalkingVisitor() { override fun visitElement(element: PsiElement) { super.visitElement(element); if (element !is PsiClass) { return } if(element.name?.startsWith("Renamed") == false) { log("Renaming $element") // arg4 = isSearchInComments // arg5 = isSearchTextOccurrences val processor = object : RenameProcessor(project, element, "Renamed" + element.name, false, false) { override fun isPreviewUsages(usages: Array<out UsageInfo>): Boolean { return false } } processor.run() } } }) } } If your project is large this will temporarily freeze intellij since it doesn't properly run on the background thread but just give it a minute. By the way, this should work on all languages that IntelliJ has a language plugin for, not just Java. Edit: Modified script to override isPreviewUsages to prevent intellij from opening confirmation dialogs
- hbn 4y agoNow I want to make a fork, DumbKeenType, where the first thing I do is append "Dumb" to the beginning of every class/filename. https://www.newyorker.com/tech/annals-of-technology/dumb-starbucks-and-the-art-of-the-hoax https://www.newyorker.com/tech/annals-of-technology/dumb-sta...
- brazzy 4y ago> in Java, the name of the file is the name of the class. You can't have the file name differ from the class inside. Actually, I'm fairly sure you can. You just need a custom classloader.
- brabel 4y agoClass files don't actually care about file names so ClassLoader has nothing to do with this. The OP problem is the source. The Java compiler won't compile a source file if none of the classes (and the only public one) in the file matches the name of the file.
- brazzy 4y ago> Class files don't actually care about file names But URLClassLoader does, which definitely has something to do with this. True, before you get there, you'd first need it to compile - but modern JDKs have a compiler API that allows customization via the StandardJavaFileManager interface, and that looks like it should be able to do the job to make source file names follow a different convention.
- rowls66 4y agoYes, commonly used ClassLoaders do care about file names and directories. The Java compiler javac does not. The javac compiler compiles compilation units which are generally files, but name does not matter.
- teraflop 4y agoNo, the file names of compilation units do matter to javac. To quote the Java Language Specification, section 7.6: > If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a class or interface is not found in a file under a name composed of the class or interface name plus an extension (such as .java or .jav) if either of the following is true: > * The class or interface is referred to by code in other ordinary compilation units of the package in which the class or interface is declared. > * The class or interface is declared public (and therefore is potentially accessible from code in other packages). and javac does indeed enforce this restriction, at least for public classes. It's an error to declare a public class called Foo in a file that's called anything except Foo.java.
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]