diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5e4f4debfbd6..a9b501329ba6 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -766,6 +766,9 @@ jobs:
- name: ide/projectui
run: ant $OPTS -f ide/projectui test
+ - name: ide/properties
+ run: ant $OPTS -f ide/properties test
+
- name: ide/refactoring.api
run: ant $OPTS -f ide/refactoring.api test
diff --git a/ide/options.editor/nbproject/project.xml b/ide/options.editor/nbproject/project.xml
index 4f97c52683e1..f48eef566007 100644
--- a/ide/options.editor/nbproject/project.xml
+++ b/ide/options.editor/nbproject/project.xml
@@ -372,6 +372,7 @@
org.netbeans.modules.php.editor
org.netbeans.modules.php.project
org.netbeans.modules.php.twig
+ org.netbeans.modules.properties
org.netbeans.modules.python.editor
org.netbeans.modules.python.source
org.netbeans.modules.ruby
diff --git a/ide/properties/nbproject/org-netbeans-modules-properties.sig b/ide/properties/nbproject/org-netbeans-modules-properties.sig
index f8b16e987552..0410dc51dc76 100644
--- a/ide/properties/nbproject/org-netbeans-modules-properties.sig
+++ b/ide/properties/nbproject/org-netbeans-modules-properties.sig
@@ -1,5 +1,5 @@
#Signature file v4.1
-#Version 1.88
+#Version 1.90
CLSS public abstract java.awt.Component
cons protected init()
@@ -1241,7 +1241,7 @@ meth public void open()
meth public void saveAs(org.openide.filesystems.FileObject,java.lang.String) throws java.io.IOException
supr org.openide.text.CloneableEditorSupport
hfds LOG,charset,fsStatusListener,myEntry,serialVersionUID
-hcls Env,Environment,EnvironmentListener,FsStatusListener,PropertiesEditorLookup,SaveImpl,StampFlag,UndoRedoStampFlagManager
+hcls Environment,EnvironmentListener,FsStatusListener,PropertiesEditorLookup,SaveImpl,StampFlag,UndoRedoStampFlagManager
CLSS public org.netbeans.modules.properties.PropertiesEditorSupport$PropertiesEditAt
outer org.netbeans.modules.properties.PropertiesEditorSupport
@@ -1520,16 +1520,7 @@ CLSS public org.netbeans.modules.properties.UtilConvert
fld public final static java.lang.String keyValueSeparators = "=: \u0009\r\n\u000c"
fld public final static java.lang.String strictKeyValueSeparators = "=:"
fld public final static java.lang.String whiteSpaceChars = " \u0009\r\n\u000c"
-meth public static java.lang.String charsToUnicodes(java.lang.String)
-meth public static java.lang.String charsToUnicodes(java.lang.String,boolean)
-meth public static java.lang.String escapeComment(java.lang.String)
-meth public static java.lang.String escapeJavaSpecialChars(java.lang.String)
-meth public static java.lang.String escapeLineContinuationChar(java.lang.String)
-meth public static java.lang.String escapeOutsideSpaces(java.lang.String)
-meth public static java.lang.String escapePropertiesSpecialChars(java.lang.String)
meth public static java.lang.String loadConvert(java.lang.String)
-meth public static java.lang.String saveConvert(java.lang.String)
-meth public static java.lang.String unicodesToChars(java.lang.String)
supr java.lang.Object
hfds hexDigit,specialSaveChars
diff --git a/ide/properties/nbproject/project.xml b/ide/properties/nbproject/project.xml
index c366b88bb912..95722f9d99aa 100644
--- a/ide/properties/nbproject/project.xml
+++ b/ide/properties/nbproject/project.xml
@@ -34,6 +34,50 @@
1.25
+
+ org.netbeans.modules.editor
+
+
+
+ 3
+ 1.122
+
+
+
+ org.netbeans.modules.editor.document
+
+
+
+ 1.44
+
+
+
+ org.netbeans.modules.editor.indent
+
+
+
+ 2
+ 1.78
+
+
+
+ org.netbeans.modules.editor.settings
+
+
+
+ 1
+ 1.92
+
+
+
+ org.netbeans.modules.options.editor
+
+
+
+ 1
+ 1.96
+
+
org.netbeans.modules.queries
@@ -100,7 +144,7 @@
- org.openide.util.ui
+ org.openide.util
@@ -108,19 +152,19 @@
- org.openide.util
+ org.openide.util.lookup
- 9.3
+ 8.0
- org.openide.util.lookup
+ org.openide.util.ui
- 8.0
+ 9.3
diff --git a/ide/properties/src/org/netbeans/modules/properties/Layer.xml b/ide/properties/src/org/netbeans/modules/properties/Layer.xml
index d1198ada2e67..774fe605d9e9 100644
--- a/ide/properties/src/org/netbeans/modules/properties/Layer.xml
+++ b/ide/properties/src/org/netbeans/modules/properties/Layer.xml
@@ -132,4 +132,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ide/properties/src/org/netbeans/modules/properties/PropertiesDataNode.java b/ide/properties/src/org/netbeans/modules/properties/PropertiesDataNode.java
index 0828618d3861..f4fb47d47aa0 100644
--- a/ide/properties/src/org/netbeans/modules/properties/PropertiesDataNode.java
+++ b/ide/properties/src/org/netbeans/modules/properties/PropertiesDataNode.java
@@ -330,11 +330,23 @@ public ProjectEncodingProperty() {
}
@Override
- public Object getValue() throws InvocationTargetException {
+ public boolean isDefaultValue() {
+ return getValue() == null;
+ }
+
+ @Override
+ public void restoreDefaultValue() throws IllegalAccessException, InvocationTargetException {
+ setValue(null);
+ }
+
+ @Override
+ public boolean supportsDefaultValue() {
+ return true;
+ }
+
+ @Override
+ public Object getValue() {
Object attribute = getDataObject().getPrimaryFile().getAttribute(PROPERTY_ENCODING);
- if (attribute == null) {
- return false;
- }
return attribute;
}
diff --git a/ide/properties/src/org/netbeans/modules/properties/PropertiesEditorSupport.java b/ide/properties/src/org/netbeans/modules/properties/PropertiesEditorSupport.java
index eccd54f227e2..81a77687c1dd 100644
--- a/ide/properties/src/org/netbeans/modules/properties/PropertiesEditorSupport.java
+++ b/ide/properties/src/org/netbeans/modules/properties/PropertiesEditorSupport.java
@@ -59,8 +59,6 @@
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.logging.Level;
@@ -74,7 +72,6 @@
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEdit;
import org.netbeans.api.queries.FileEncodingQuery;
-import org.netbeans.modules.properties.PropertiesEncoding.PropCharset;
import org.netbeans.modules.properties.PropertiesEncoding.PropCharsetEncoder;
import org.openide.ErrorManager;
import org.openide.awt.UndoRedo;
@@ -109,56 +106,62 @@
import org.openide.util.WeakListeners;
import org.openide.windows.CloneableOpenSupport;
import org.openide.util.Task;
-import org.openide.util.TaskListener;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.CloneableTopComponent;
import org.openide.windows.TopComponent;
+
import static java.util.logging.Level.FINER;
-import javax.swing.*;
+
import org.openide.filesystems.StatusDecorator;
-/**
+import static java.util.logging.Level.FINE;
+
+/**
* Support for viewing .properties files (EditCookie) by opening them in a text editor.
*
- * @author Petr Jiricka, Peter Zavadsky
+ * @author Petr Jiricka, Peter Zavadsky
* @see org.openide.text.CloneableEditorSupport
*/
-public class PropertiesEditorSupport extends CloneableEditorSupport
+public class PropertiesEditorSupport extends CloneableEditorSupport
implements EditCookie, EditorCookie.Observable, PrintCookie, CloseCookie, Serializable, SaveAsCapable {
-
+
/** error manager for CloneableEditorSupport logging and error reporting */
static final Logger LOG = Logger.getLogger("org.netbeans.modules.properties.PropertiesEditorSupport"); // NOI18N
-
+
/** */
private FileStatusListener fsStatusListener;
-
+
/** Visible view of underlying file entry */
transient PropertiesFileEntry myEntry;
-
+
/** Generated serial version UID. */
static final long serialVersionUID =1787354011149868490L;
-
+
private Charset charset;
-
- /** Constructor. */
+
+ /**
+ * Constructor.
+ *
+ * @param entry
+ */
public PropertiesEditorSupport(PropertiesFileEntry entry) {
super(new Environment(entry), new ProxyLookup(Lookups.singleton(entry.getDataObject()), entry.getDataObject().getLookup()));
this.myEntry = entry;
}
-
+
@Override
protected Pane createPane() {
return (Pane) MultiViews.createCloneableMultiView(PropertiesDataLoader.PROPERTIES_MIME_TYPE, getDataObject());
}
-
+
/** Getter for the environment that was provided in the constructor.
* @return the environment
*/
final CloneableEditorSupport.Env desEnv() {
return (CloneableEditorSupport.Env) env;
}
-
- /**
+
+ /**
* Overrides superclass method.
* Should test whether all data is saved, and if not, prompt the user
* to save. Called by my topcomponent when it wants to close its last topcomponent, but the table editor may still be open
@@ -177,7 +180,7 @@ protected boolean canClose () {
return super.canClose();
}
}
-
+
/** Getter of the data object that this support is associated with.
* @return data object passed in constructor
*/
@@ -189,34 +192,32 @@ private boolean isEnvReadOnly() {
CloneableEditorSupport.Env myEnv = desEnv();
return myEnv instanceof Environment && !((Environment) myEnv).getFileImpl().canWrite();
}
-
+
/**
*
*/
- final class FsStatusListener implements FileStatusListener, Runnable {
-
- /**
- */
+ private final class FsStatusListener implements FileStatusListener, Runnable {
+
+ @Override
public void annotationChanged(FileStatusEvent ev) {
if (ev.isNameChange() && ev.hasChanged(myEntry.getFile())) {
Mutex.EVENT.writeAccess(this);
}
}
-
- /**
- */
+
+ @Override
public void run() {
updateEditorDisplayNames();
}
}
-
+
/**
*/
private void attachStatusListener() {
if (fsStatusListener != null) {
return; //already attached
}
-
+
FileSystem fs;
try {
fs = myEntry.getFile().getFileSystem();
@@ -224,21 +225,21 @@ private void attachStatusListener() {
ErrorManager.getDefault().notify(ErrorManager.ERROR, ex);
return;
}
-
+
fsStatusListener = new FsStatusListener();
fs.addFileStatusListener(
FileUtil.weakFileStatusListener(fsStatusListener, fs));
}
-
+
/**
*/
private void updateEditorDisplayNames() {
assert EventQueue.isDispatchThread();
-
+
final String title = messageName();
final String htmlTitle = messageHtmlName();
final String toolTip = messageToolTip();
- Enumeration en = allEditors.getComponents();
+ Enumeration en = allEditors.getComponents();
while (en.hasMoreElements()) {
TopComponent tc = (TopComponent) en.nextElement();
tc.setDisplayName(title);
@@ -246,7 +247,7 @@ private void updateEditorDisplayNames() {
tc.setToolTipText(toolTip);
}
}
-
+
/**
*/
@Override
@@ -255,7 +256,7 @@ protected void initializeCloneableEditor(CloneableEditor editor) {
}
/**
- * Overrides superclass method.
+ * Overrides superclass method.
* Let's the super method create the document and also annotates it
* with Title and StreamDescription properities.
* @param kit kit to user to create the document
@@ -264,31 +265,31 @@ protected void initializeCloneableEditor(CloneableEditor editor) {
@Override
protected StyledDocument createStyledDocument(EditorKit kit) {
StyledDocument document = super.createStyledDocument(kit);
-
+
// Set additional proerties to document.
// Set document name property. Used in CloneableEditorSupport.
document.putProperty(Document.TitleProperty, myEntry.getFile().toString());
-
+
// Set dataobject to stream desc property.
document.putProperty(Document.StreamDescriptionProperty, myEntry.getDataObject());
-
+
// hook the document to listen for any changes to update changes by
// reparsing the document
document.addDocumentListener(new javax.swing.event.DocumentListener() {
- public void insertUpdate(javax.swing.event.DocumentEvent e) { changed();}
- public void changedUpdate(javax.swing.event.DocumentEvent e) { changed();}
- public void removeUpdate(javax.swing.event.DocumentEvent e) { changed();}
+ @Override public void insertUpdate(javax.swing.event.DocumentEvent e) { changed();}
+ @Override public void changedUpdate(javax.swing.event.DocumentEvent e) { changed();}
+ @Override public void removeUpdate(javax.swing.event.DocumentEvent e) { changed();}
private void changed() {
- myEntry.getHandler().autoParse();
+ myEntry.getHandler().autoParse();
}
});
-
+
return document;
}
/**
* Reads the file from the stream, filter the guarded section
- * comments, and mark the sections in the editor. Overrides superclass method.
+ * comments, and mark the sections in the editor. Overrides superclass method.
* @param document the document to read into
* @param inputStream the open stream to read from
* @param editorKit the associated editor kit
@@ -299,16 +300,12 @@ private void changed() {
@Override
protected void loadFromStreamToKit(StyledDocument document, InputStream inputStream, EditorKit editorKit) throws IOException, BadLocationException {
final Charset c = getCharset();
- final Reader reader = new BufferedReader(new InputStreamReader(inputStream, c));
-
- try {
+ try (Reader reader = new BufferedReader(new InputStreamReader(inputStream, c))) {
editorKit.read(reader, document, 0);
- } finally {
- reader.close();
}
}
- /**
+ /**
* Adds new lines according actual value of newLineType variable.
* Overrides superclass method.
* @param document the document to write from
@@ -336,7 +333,7 @@ protected void saveFromKitToStream(StyledDocument document, EditorKit editorKit,
writer.close();
}
}
-
+
private Charset getCharset() {
if (charset == null) {
charset = FileEncodingQuery.getEncoding(myEntry.getDataObject().getPrimaryFile());
@@ -348,8 +345,8 @@ void resetCharset() {
charset = null;
}
- /**
- * Adds a save cookie if the document has been marked modified. Overrides superclass method.
+ /**
+ * Adds a save cookie if the document has been marked modified. Overrides superclass method.
* @return true if the environment accepted being marked as modified
* or false if it refused it and the document should still be unmodified
*/
@@ -367,17 +364,13 @@ protected boolean notifyModified () {
((Environment)env).addSaveCookie();
- return true;
+ return true;
}
-
+
@Override
protected Task reloadDocument(){
Task tsk = super.reloadDocument();
- tsk.addTaskListener(new TaskListener(){
- public void taskFinished(Task task){
- myEntry.getHandler().autoParse();
- }
- });
+ tsk.addTaskListener(task -> myEntry.getHandler().autoParse());
return tsk;
}
@@ -385,10 +378,10 @@ public void taskFinished(Task task){
@Override
protected void notifyUnmodified () {
super.notifyUnmodified();
-
+
((Environment)env).removeSaveCookie();
}
-
+
/**
*/
@Override
@@ -396,7 +389,7 @@ public void open() {
super.open();
attachStatusListener();
}
-
+
/** Overrides superclass method. Adds checking for opened Table panel. */
@Override
protected void notifyClosed() {
@@ -413,11 +406,12 @@ protected void notifyClosed() {
}
}
- /**
- * Overrides superclass abstract method.
+ /**
+ * Overrides superclass abstract method.
* Message to display when an object is being opened.
* @return the message or null if nothing should be displayed
*/
+ @Override
protected String messageOpening() {
return NbBundle.getMessage(
PropertiesEditorSupport.class,
@@ -425,12 +419,13 @@ protected String messageOpening() {
getFileLabel()
);
}
-
+
/**
- * Overrides superclass abstract method.
+ * Overrides superclass abstract method.
* Message to display when an object has been opened.
* @return the message or null if nothing should be displayed
*/
+ @Override
protected String messageOpened() {
return NbBundle.getMessage(
PropertiesEditorSupport.class,
@@ -438,20 +433,21 @@ protected String messageOpened() {
getFileLabel()
);
}
-
+
private String getFileLabel() {
PropertiesDataObject propDO = (PropertiesDataObject) myEntry.getDataObject();
return propDO.getPrimaryFile().getNameExt();
}
-
- /**
- * Overrides superclass abstract method.
+
+ /**
+ * Overrides superclass abstract method.
* Constructs message that should be used to name the editor component.
* @return name of the editor
*/
+ @Override
protected String messageName () {
if (!myEntry.getDataObject().isValid()) {
- return ""; //NOI18N
+ return ""; //NOI18N
}
return DataEditorSupport.annotateName(getFileLabel(), false, isModified(), !myEntry.getFile().canWrite());
}
@@ -464,7 +460,7 @@ protected String messageHtmlName () {
}
String rawName = getFileLabel();
-
+
String annotatedName = null;
final FileObject entry = myEntry.getFile();
try {
@@ -486,16 +482,17 @@ protected String messageHtmlName () {
} catch (FileStateInvalidException ex) {
//do nothing and fall through
}
-
+
String name = (annotatedName != null) ? annotatedName : /*XXX escape HTML content*/rawName;
return DataEditorSupport.annotateName(name, true, isModified(), !myEntry.getFile().canWrite());
}
-
- /**
+
+ /**
* Overrides superclass abstract method.
* Is modified and is being closed.
* @return text to show to the user
*/
+ @Override
protected String messageSave () {
return NbBundle.getMessage (
PropertiesEditorSupport.class,
@@ -503,42 +500,43 @@ protected String messageSave () {
getFileLabel()
);
}
-
- /**
+
+ /**
* Overrides superclass abstract method.
* Text to use as tooltip for component.
* @return text to show to the user
*/
+ @Override
protected String messageToolTip () {
// copied from DataEditorSupport, more or less
FileObject fo = myEntry.getFile();
return DataEditorSupport.toolTip(fo, isModified(), !myEntry.getFile().canWrite());
}
-
- /** Overrides superclass method. Gets UndoRedo manager which maps
+
+ /** Overrides superclass method. Gets UndoRedo manager which maps
* UndoalbleEdit's to StampFlag's. */
@Override
protected UndoRedo.Manager createUndoRedoManager () {
return new UndoRedoStampFlagManager();
}
-
- /**
- * Helper method. Hack on superclass getUndoRedo() method, to widen its protected modifier.
- * Needs to be accessed from outside this class (in PropertiesOpen).
- * @see PropertiesOpen
+
+ /**
+ * Helper method. Hack on superclass getUndoRedo() method, to widen its protected modifier.
+ * Needs to be accessed from outside this class (in PropertiesOpen).
+ * @see PropertiesOpen
*/
UndoRedo.Manager getUndoRedoManager() {
return super.getUndoRedo();
}
-
- /**
+
+ /**
* Helper method. Used only by PropertiesOpen support when closing last Table component.
- * Note: It's quite ugly by-pass of notifyClosed() method. Should be revised.
+ * Note: It's quite ugly by-pass of notifyClosed() method. Should be revised.
*/
void forceNotifyClosed() {
super.notifyClosed();
}
-
+
/** Helper method. Saves this entry. */
private void saveThisEntry() throws IOException {
FileSystem.AtomicAction aa = new SaveImpl(this);
@@ -555,7 +553,7 @@ private void saveThisEntry() throws IOException {
final void superSaveDoc() throws IOException {
super.saveDocument();
}
-
+
/**
* Save the document under a new file name and/or extension.
* @param folder New folder to save the DataObject to.
@@ -563,6 +561,7 @@ final void superSaveDoc() throws IOException {
* @throws java.io.IOException If the operation failed
* @since 6.3
*/
+ @Override
public void saveAs( FileObject folder, String fileName ) throws IOException {
//ask the user for a new file name to save to
String newExtension = FileUtil.getExtension( fileName );
@@ -601,7 +600,7 @@ public void saveAs( FileObject folder, String fileName ) throws IOException {
}
}
}
-
+
private String getFileNameNoExtension(String fileName) {
int index = fileName.lastIndexOf("."); // NOI18N
@@ -612,21 +611,22 @@ private String getFileNameNoExtension(String fileName) {
}
}
-
- /**
+
+ /**
* Save the document to a new file.
- * @param output
+ * @param output
* @exception IOException on I/O error
* @since 6.3
*/
private void saveDocumentAs( final OutputStream output ) throws IOException {
final StyledDocument myDoc = getDocument();
-
+
// save the document as a reader
class SaveAsWriter implements Runnable {
private IOException ex;
+ @Override
public void run() {
try {
OutputStream os = null;
@@ -663,7 +663,7 @@ public void after() throws IOException {
saveAsWriter.after();
}
- /** Helper method.
+ /** Helper method.
* @return whether there is an table view opened */
public synchronized boolean hasOpenedTableComponent() {
PropertiesDataObject dataObject = (PropertiesDataObject) myEntry.getDataObject();
@@ -672,47 +672,22 @@ public synchronized boolean hasOpenedTableComponent() {
}
return dataObject.getOpenSupport().hasOpenedTableComponent();
}
-
+
/**
* Helper method.
* @return whether there is an open editor component. */
public synchronized boolean hasOpenedEditorComponent() {
- Enumeration en = allEditors.getComponents ();
+ Enumeration en = allEditors.getComponents();
return en.hasMoreElements ();
}
- /** Class which exist only due comaptibility with version 3.0. */
- private static final class Env extends Environment {
- /** Generated Serialized Version UID. */
- static final long serialVersionUID = -9218186467757330339L;
-
- /** Used for deserialization. */
- private PropertiesFileEntry entry;
-
- /** */
- public Env(PropertiesFileEntry entry) {
- super(entry);
- }
-
- /** Adds passing entry field to superclass. */
- private void readObject(java.io.ObjectInputStream in)
- throws IOException, ClassNotFoundException {
- in.defaultReadObject();
-
- if (this.entry != null) {
- super.entry = this.entry;
- }
- }
- }
-
-
/** Nested class. Implementation of ClonableEditorSupport.Env interface. */
private static class Environment implements CloneableEditorSupport.Env,
PropertyChangeListener, SaveCookie {
-
+
/** generated Serialized Version UID */
static final long serialVersionUID = 354528097109874355L;
-
+
/** Entry on which is support build. */
private PropertiesFileEntry entry;
@@ -723,15 +698,15 @@ private static class Environment implements CloneableEditorSupport.Env,
* This file object can be changed by a call to refresh file.
*/
private transient FileObject fileObject;
-
+
/** Spport for firing of property changes. */
private transient PropertyChangeSupport propSupp;
-
+
/** Support for firing of vetoable changes. */
private transient VetoableChangeSupport vetoSupp;
private transient EnvironmentListener envListener;
-
+
/** Constructor.
* @param obj this support should be associated with
*/
@@ -756,23 +731,23 @@ protected final DataObject getDataObject() {
return entry.getDataObject();
}
/** Implements CloneableEditorSupport.Env inetrface. Adds property listener. */
+ @Override
public void addPropertyChangeListener(PropertyChangeListener l) {
LOG.finer("Environment.addPropertyChangeListener(...)"); //NOI18N
prop().addPropertyChangeListener (l);
}
-
+
/** Accepts property changes from entry and fires them to own listeners. */
+ @Override
public void propertyChange(PropertyChangeEvent evt) {
- if (LOG.isLoggable(FINER)) {
- LOG.finer("Environment.propertyChange(" //NOI18N
- + evt.getPropertyName()
- + ", " + evt.getOldValue() //NOI18N
- + ", " + evt.getNewValue() //NOI18N
- + ')');
- }
+ LOG.finer(() -> "Environment.propertyChange(" //NOI18N
+ + evt.getPropertyName()
+ + ", " + evt.getOldValue() //NOI18N
+ + ", " + evt.getNewValue() //NOI18N
+ + ')');
// We will handle the object invalidation here.
- if(DataObject.PROP_VALID.equals(evt.getPropertyName ())) {
+ if(DataObject.PROP_VALID.equals(evt.getPropertyName ())) {
// do not check it if old value is not true
if (Boolean.FALSE.equals(evt.getOldValue())) {
return;
@@ -781,7 +756,7 @@ public void propertyChange(PropertyChangeEvent evt) {
// loosing validity
PropertiesEditorSupport support = (PropertiesEditorSupport)findCloneableOpenSupport();
if(support != null) {
-
+
// mark the object as not being modified, so nobody
// will ask for save
unmarkModified();
@@ -796,20 +771,23 @@ public void propertyChange(PropertyChangeEvent evt) {
);
}
}
-
+
/** Implements CloneableEditorSupport.Env inetrface. Removes property listener. */
+ @Override
public void removePropertyChangeListener(PropertyChangeListener l) {
LOG.finer("Environment.removePropertyChangeListener(...)"); //NOI18N
prop().removePropertyChangeListener (l);
}
-
+
/** Implements CloneableEditorSupport.Env inetrface. Adds veto listener. */
+ @Override
public void addVetoableChangeListener(VetoableChangeListener l) {
LOG.finer("Environment.addVetoableChangeListener(...)"); //NOI18N
veto().addVetoableChangeListener (l);
}
-
+
/** Implements CloneableEditorSupport.Env inetrface. Removes veto listener. */
+ @Override
public void removeVetoableChangeListener(VetoableChangeListener l) {
LOG.finer("Environment.removeVetoableChangeListener(...)"); //NOI18N
veto().removeVetoableChangeListener (l);
@@ -821,6 +799,7 @@ public void removeVetoableChangeListener(VetoableChangeListener l) {
* state and the CloneableOpenSupport cannot be found for associated
* entry object
*/
+ @Override
public CloneableOpenSupport findCloneableOpenSupport() {
return (PropertiesEditorSupport)entry.getCookieSet().getCookie(EditCookie.class);
}
@@ -832,15 +811,17 @@ public CloneableOpenSupport findCloneableOpenSupport() {
* referenced to does not exist anymore.
* @return true or false depending on its state
*/
+ @Override
public boolean isValid() {
return entry.getDataObject().isValid();
}
-
+
/**
* Implements CloneableEditorSupport.Env interface.
* Test whether the object is modified or not.
* @return true if the object is modified
*/
+ @Override
public boolean isModified() {
return entry.isModified();
}
@@ -853,26 +834,28 @@ public boolean isModified() {
* (for example when the file is readonly), when such exception
* is the support should discard all previous changes
*/
+ @Override
public void markModified() throws java.io.IOException {
LOG.finer("Environment.markModified()"); //NOI18N
if (fileLock == null || !fileLock.isValid()) {
fileLock = entry.takeLock();
}
-
+
entry.setModified(true);
}
-
+
/**
* Implements CloneableEditorSupport.Env interface.
* Reverse method that can be called to make the environment
* unmodified.
*/
+ @Override
public void unmarkModified() {
LOG.finer("Environment.unmarkModified()"); //NOI18N
if (fileLock != null && fileLock.isValid()) {
fileLock.releaseLock();
}
-
+
entry.setModified(false);
}
/**
@@ -895,13 +878,15 @@ final void updateDocumentProperty () {
* Mime type of the document.
* @return the mime type to use for the document
*/
+ @Override
public String getMimeType() {
return getFileImpl().getMIMEType();
}
-
+
/**
* Implements CloneableEditorSupport.Env interface.
* The time when the data has been modified. */
+ @Override
public Date getTime() {
// #32777 - refresh file object and return always the actual time
getFileImpl().refresh();
@@ -928,7 +913,7 @@ protected final void changeFile () {
// lockAgain = true;
// =====
if(fileLock.isValid()) {
- LOG.fine("changeFile releaseLock: " + fileLock + " for " + fileObject); // NOI18N
+ LOG.log(FINE, "changeFile releaseLock: {0} for {1}", new Object[]{fileLock, fileObject}); // NOI18N
fileLock.releaseLock ();
lockAgain = true;
} else {
@@ -943,7 +928,7 @@ protected final void changeFile () {
boolean wasNull = fileObject == null;
fileObject = newFile;
- LOG.fine("changeFile: " + newFile + " for " + fileObject); // NOI18N
+ LOG.log(FINE, "changeFile: {0} for {1}", new Object[]{newFile, fileObject}); // NOI18N
if (envListener != null)
fileObject.removeFileChangeListener(envListener);
envListener = new EnvironmentListener(this);
@@ -952,7 +937,7 @@ protected final void changeFile () {
if (lockAgain) { // refresh lock
try {
fileLock = entry.takeLock ();
- LOG.fine("changeFile takeLock: " + fileLock + " for " + fileObject); // NOI18N
+ LOG.log(FINE, "changeFile takeLock: {0} for {1}", new Object[]{fileLock, fileObject}); // NOI18N
} catch (IOException e) {
Logger.getLogger(PropertiesEditorSupport.class.getName()).log(Level.WARNING, null, e);
}
@@ -961,28 +946,30 @@ protected final void changeFile () {
firePropertyChange("expectedTime", null, getTime()); // NOI18N
}
}
-
+
/**
* Implements CloneableEditorSupport.Env interface.
* Obtains the input stream.
* @exception IOException if an I/O error occures
*/
+ @Override
public InputStream inputStream() throws IOException {
LOG.finer("Environment.inputStream()"); //NOI18N
return getFileImpl().getInputStream();
}
-
+
/**
* Implements CloneableEditorSupport.Env interface.
* Obtains the output stream.
* @exception IOException if an I/O error occures
*/
+ @Override
public OutputStream outputStream() throws IOException {
LOG.finer("Environment.outputStream()"); //NOI18N
if (fileLock == null || !fileLock.isValid()) {
fileLock = entry.takeLock ();
}
- LOG.fine("outputStream after takeLock: " + fileLock + " for " + fileObject); // NOI18N
+ LOG.fine(() -> "outputStream after takeLock: " + fileLock + " for " + fileObject); // NOI18N
try {
return getFileImpl ().getOutputStream (fileLock);
} catch (IOException fse) {
@@ -991,17 +978,18 @@ public OutputStream outputStream() throws IOException {
if (fileLock == null || !fileLock.isValid()) {
fileLock = entry.takeLock ();
}
- LOG.fine("ugly workaround for #40552: " + fileLock + " for " + fileObject); // NOI18N
+ LOG.fine(() -> "ugly workaround for #40552: " + fileLock + " for " + fileObject); // NOI18N
return getFileImpl ().getOutputStream (fileLock);
}
// return entry.getFile().getOutputStream(fileLock);
}
/**
- * Implements SaveCookie interface.
+ * Implements SaveCookie interface.
* Invoke the save operation.
* @throws IOException if the object could not be saved
*/
+ @Override
public void save() throws IOException {
LOG.finer("Environment.save()"); //NOI18N
// Do saving job. Note it gets editor support, not open support.
@@ -1016,7 +1004,7 @@ public void save() throws IOException {
private void firePropertyChange (String name, Object oldValue, Object newValue) {
prop().firePropertyChange (name, oldValue, newValue);
}
-
+
/** Fires vetoable change.
* @param name the name of property that changed
* @param oldValue old value
@@ -1025,7 +1013,7 @@ private void firePropertyChange (String name, Object oldValue, Object newValue)
private void fireVetoableChange (String name, Object oldValue, Object newValue) throws PropertyVetoException {
veto ().fireVetoableChange (name, oldValue, newValue);
}
-
+
/** Lazy getter for property change support. */
private PropertyChangeSupport prop() {
synchronized (this) {
@@ -1033,10 +1021,10 @@ private PropertyChangeSupport prop() {
propSupp = new PropertyChangeSupport (this);
}
}
-
+
return propSupp;
}
-
+
/** Lazy getter for vetoable support. */
private VetoableChangeSupport veto() {
synchronized (this) {
@@ -1046,7 +1034,7 @@ private VetoableChangeSupport veto() {
}
return vetoSupp;
}
-
+
/** Helper method. Adds save cookie to the entry. */
private void addSaveCookie() {
LOG.finer("Environment.addSaveCookie(...)"); //NOI18N
@@ -1061,26 +1049,24 @@ private void addSaveCookie() {
dataObject.getCookieSet0().add(this);
}
}
-
+
/** Helper method. Removes save cookie from the entry. */
private void removeSaveCookie() {
LOG.finer("Environment.removeSaveCookie(...)"); //NOI18N
// remove Save cookie from the entry
SaveCookie sc = entry.getCookie(SaveCookie.class);
-
+
if (sc != null && sc.equals(this)) {
entry.getCookieSet().remove(this);
}
final SaveCookie cookie = this;
- PropertiesRequestProcessor.getInstance().post(new Runnable() {
- public void run() {
- PropertiesDataObject dataObject = (PropertiesDataObject) getDataObject();
- dataObject.updateModificationStatus();
- dataObject.getCookieSet0().remove(cookie);
- }
+ PropertiesRequestProcessor.getInstance().post(() -> {
+ PropertiesDataObject dataObject = (PropertiesDataObject) getDataObject();
+ dataObject.updateModificationStatus();
+ dataObject.getCookieSet0().remove(cookie);
});
}
-
+
/** Called from the EnvironmnetListener
* @param expected is the change expected
* @param time of the change
@@ -1101,7 +1087,7 @@ final void fileRenamed () {
//#151787: Sync timestamp when svn client changes timestamp externally during rename.
firePropertyChange("expectedTime", null, getTime()); // NOI18N
}
-
+
/** Called from the EnvironmentListener.
* The components are going to be closed anyway and in case of
* modified document its asked before if to save the change. */
@@ -1112,25 +1098,29 @@ private void fileRemoved() {
} catch(PropertyVetoException pve) {
// Ignore it and close anyway. File doesn't exist anymore.
}
-
+
firePropertyChange(PROP_VALID, Boolean.TRUE, Boolean.FALSE);
}
+
+ PropertiesFileEntry getEntry() {
+ return entry;
+ }
} // End of nested class Environment.
-
+
/** Weak listener on file object that notifies the Environment object
* that a file has been modified. */
private static final class EnvironmentListener extends FileChangeAdapter {
-
+
/** Reference of Environment */
private Reference reference;
-
+
/** @param environment Environment to use
*/
public EnvironmentListener(Environment environment) {
LOG.finer("new EnvironmentListener()"); //NOI18N
- reference = new WeakReference(environment);
+ reference = new WeakReference<>(environment);
}
@Override
@@ -1142,7 +1132,7 @@ public void fileDeleted(FileEvent fe) {
}
// super.fileDeleted(fe);
}
-
+
/** Fired when a file is changed.
* @param fe the event describing context where action has taken place
*/
@@ -1150,10 +1140,10 @@ public void fileDeleted(FileEvent fe) {
public void fileChanged(FileEvent evt) {
if (LOG.isLoggable(FINER)) {
LOG.finer("EnviromentListener.fileChanged(...)"); //NOI18N
- LOG.finer(" - original file: " //NOI18N
- + FileUtil.getFileDisplayName(evt.getFile()));
- LOG.finer(" - current file: " //NOI18N
- + FileUtil.getFileDisplayName((FileObject) evt.getSource()));
+ LOG.log(Level.FINER, " - original file: ", //NOI18N
+ FileUtil.getFileDisplayName(evt.getFile()));
+ LOG.log(Level.FINER, " - current file: ", //NOI18N
+ FileUtil.getFileDisplayName((FileObject) evt.getSource()));
}
//see #160338
if (evt.firedFrom(SaveImpl.DEFAULT)) {
@@ -1172,17 +1162,17 @@ public void fileChanged(FileEvent evt) {
// #16403. See DataEditorSupport.EnvListener.
if(evt.getFile().isVirtual()) {
- environment.entry.getFile().removeFileChangeListener(this);
+ environment.getEntry().getFile().removeFileChangeListener(this);
// File doesn't exist on disk -> simulate env is invalid,
// even the fileObject could be valid, see VCS FS.
environment.fileRemoved();
- environment.entry.getFile().addFileChangeListener(this);
+ environment.getEntry().getFile().addFileChangeListener(this);
} else {
environment.fileChanged(evt.isExpected(), evt.getTime());
}
}
}
-
+
@Override
public void fileRenamed(FileRenameEvent fe) {
Environment myEnv = this.reference.get();
@@ -1192,32 +1182,36 @@ public void fileRenamed(FileRenameEvent fe) {
}
}
} // End of nested class EnvironmentListener.
-
+
/** Inner class for opening editor view at a given key. */
public class PropertiesEditAt implements EditCookie {
/** Key at which should be pane opened. (Cursor will be at the position of that key). */
private String key;
-
-
+
+
/** Constructor. */
PropertiesEditAt(String key) {
this.key = key;
}
-
-
- /** Setter for key. */
+
+
+ /**
+ * Setter for key.
+ * @param key
+ */
public void setKey(String key) {
this.key = key;
}
-
+
/** Implementation of EditCookie interface. */
+ @Override
public void edit() {
CloneableTopComponent ctc = PropertiesEditorSupport.super.openCloneableTopComponent();
ctc.requestActive();
-
+
PropertiesEditor editor = ctc.getLookup().lookup(PropertiesEditor.class);
-
+
Element.ItemElem item = myEntry.getHandler().getStructure().getItem(key);
if (item != null) {
int offset = item.getKeyElem().getBounds().getBegin().getOffset();
@@ -1228,7 +1222,7 @@ public void edit() {
}
} // End of inner class PropertiesEditAt.
-
+
/** Cloneable top component to hold the editor kit. */
@Messages("CTL_SourceTabCaption=&Source")
@MultiViewElement.Registration(
@@ -1238,29 +1232,33 @@ public void edit() {
preferredID="properties.source",
mimeType=PropertiesDataLoader.PROPERTIES_MIME_TYPE,
position=1
- )
+ )
public static class PropertiesEditor extends CloneableEditor implements MultiViewElement {
-
+
/** Holds the file being edited. */
+ @SuppressWarnings("ProtectedField") // API
protected transient PropertiesFileEntry entry;
-
+
/** Listener for entry's save cookie changes. */
private transient PropertyChangeListener saveCookieLNode;
-
+
/** Generated serial version UID. */
static final long serialVersionUID =-2702087884943509637L;
private MultiViewElementCallback callback;
private transient JToolBar bar;
-
+
private transient PropertiesEditorLookup peLookup;
private transient Lookup originalLookup;
-
+
/** Constructor for deserialization */
public PropertiesEditor() {
super();
}
-
- /** Creates new editor */
+
+ /**
+ * Creates new editor
+ * @param lookup
+ */
public PropertiesEditor(Lookup lookup) {
super(lookup.lookup(PropertiesEditorSupport.class));
PropertiesEditorSupport support = lookup.lookup(PropertiesEditorSupport.class);
@@ -1270,27 +1268,24 @@ public PropertiesEditor(Lookup lookup) {
/** Initializes object, used in construction and deserialization. */
private void initialize(PropertiesFileEntry entry) {
this.entry = entry;
-
+
Node n = entry.getNodeDelegate ();
setActivatedNodes (new Node[] { n });
-
+
updateName();
-
+
// entry to the set of listeners
- saveCookieLNode = new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- if (Node.PROP_COOKIE.equals(evt.getPropertyName()) ||
- DataObject.PROP_NAME.equals(evt.getPropertyName()))
- {
- updateName();
- }
+ saveCookieLNode = (PropertyChangeEvent evt) -> {
+ if (Node.PROP_COOKIE.equals(evt.getPropertyName())
+ || DataObject.PROP_NAME.equals(evt.getPropertyName())) {
+ updateName();
}
};
this.entry.addPropertyChangeListener(WeakListeners.propertyChange(saveCookieLNode, this.entry));
}
/**
- * Overrides superclass method.
+ * Overrides superclass method.
* When closing last view, also close the document.
* @return true if close succeeded
*/
@@ -1302,19 +1297,19 @@ protected boolean closeLast () {
/** Overrides superclass method. Gets Icon. */
@Override
public Image getIcon () {
- PropertiesDataObject propDO = (PropertiesDataObject) getDataObject();
+ PropertiesDataObject propDO = getDataObject();
return ImageUtilities.loadImage(
propDO.isMultiLocale()
? "org/netbeans/modules/properties/propertiesLocale.gif" // NOI18N
: "org/netbeans/modules/properties/propertiesObject.png"); // NOI18N
}
-
+
/** Overrides superclass method. Gets help context. */
@Override
public HelpCtx getHelpCtx() {
return new HelpCtx(Util.HELP_ID_EDITLOCALE);
}
-
+
/** Getter for pane. */
private JEditorPane getPane() {
return pane;
@@ -1332,7 +1327,7 @@ public Lookup getLookup() {
}
return peLookup;
}
-
+
@Override
public JComponent getVisualRepresentation() {
return this;
@@ -1347,7 +1342,7 @@ public void componentDeactivated() {
public void componentClosed() {
super.componentClosed();
}
-
+
@Override
public JComponent getToolbarRepresentation() {
JToolBar toolBar = bar;
@@ -1355,8 +1350,8 @@ public JComponent getToolbarRepresentation() {
JEditorPane lPane = getEditorPane();
if (lPane != null) {
Document doc = lPane.getDocument();
- if (doc instanceof NbDocument.CustomToolbar) {
- toolBar = ((NbDocument.CustomToolbar)doc).createToolbar(lPane);
+ if (doc instanceof NbDocument.CustomToolbar customToolbar) {
+ toolBar = customToolbar.createToolbar(lPane);
}
}
if (toolBar == null) {
@@ -1375,12 +1370,13 @@ public void setMultiViewCallback(MultiViewElementCallback callback) {
}
@Messages({
+ "# {0} - filename",
"MSG_SaveModified=File {0} is modified. Save?"
})
@Override
public CloseOperationState canCloseElement() {
final CloneableEditorSupport sup = getLookup().lookup(CloneableEditorSupport.class);
- Enumeration en = getReference().getComponents();
+ Enumeration en = getReference().getComponents();
if (en.hasMoreElements()) {
en.nextElement();
if (en.hasMoreElements()) {
@@ -1388,7 +1384,7 @@ public CloseOperationState canCloseElement() {
return CloseOperationState.STATE_OK;
}
}
-
+
PropertiesDataObject dataObject = getDataObject();
if (dataObject.isModified()) {
AbstractAction save = new AbstractAction() {
@@ -1403,7 +1399,7 @@ public void actionPerformed(ActionEvent e) {
};
save.putValue(Action.LONG_DESCRIPTION, Bundle.MSG_SaveModified(FileUtil.getFileDisplayName(dataObject.getPrimaryFile())));
return MultiViewFactory.createUnsafeCloseState("editor", save, null);
- }
+ }
return CloseOperationState.STATE_OK;
}
@@ -1451,20 +1447,15 @@ public void requestActive() {
@Override
public void updateName() {
super.updateName();
- Mutex.EVENT.writeAccess(
- new Runnable() {
- @Override
- public void run() {
- if (callback != null) {
- TopComponent tc = callback.getTopComponent();
- tc.setHtmlDisplayName(getHtmlDisplayName());
- tc.setDisplayName(getDisplayName());
- tc.setName(getName());
- tc.setToolTipText(getToolTipText());
- }
- }
+ Mutex.EVENT.writeAccess(() -> {
+ if (callback != null) {
+ TopComponent tc = callback.getTopComponent();
+ tc.setHtmlDisplayName(getHtmlDisplayName());
+ tc.setDisplayName(getDisplayName());
+ tc.setName(getName());
+ tc.setToolTipText(getToolTipText());
}
- );
+ });
}
@Override
@@ -1475,23 +1466,22 @@ public void open() {
super.open();
}
}
-
+
private PropertiesDataObject getDataObject() {
return (PropertiesDataObject) ((PropertiesEditorSupport) cloneableEditorSupport()).getDataObject();
}
-
+
} // End of nested class PropertiesEditor.
-
+
/** Inner class. UndoRedo manager which saves a StampFlag
* for each UndoAbleEdit.
*/
class UndoRedoStampFlagManager extends UndoRedo.Manager {
-
+
/** Hash map of weak reference keys (UndoableEdit's) to their StampFlag's. */
- WeakHashMap stampFlags
- = new WeakHashMap(5);
-
+ WeakHashMap stampFlags = new WeakHashMap<>(5);
+
/** Overrides superclass method. Adds StampFlag to UndoableEdit. */
@Override
public synchronized boolean addEdit(UndoableEdit anEdit) {
@@ -1500,16 +1490,16 @@ public synchronized boolean addEdit(UndoableEdit anEdit) {
PropertiesEditorSupport.this.myEntry.atomicUndoRedoFlag ));
return super.addEdit(anEdit);
}
-
+
/** Overrides superclass method. Adds StampFlag to UndoableEdit. */
@Override
public boolean replaceEdit(UndoableEdit anEdit) {
- stampFlags.put(anEdit, new StampFlag(System.currentTimeMillis(),
+ stampFlags.put(anEdit, new StampFlag(System.currentTimeMillis(),
// ((PropertiesDataObject)PropertiesEditorSupport.this.myEntry.getDataObject()).getOpenSupport().atomicUndoRedoFlag ));
PropertiesEditorSupport.this.myEntry.atomicUndoRedoFlag ));
return super.replaceEdit(anEdit);
}
-
+
/** Overrides superclass method. Updates time stamp for the edit. */
@Override
public synchronized void undo() throws CannotUndoException {
@@ -1520,7 +1510,7 @@ public synchronized void undo() throws CannotUndoException {
stampFlags.put(anEdit, new StampFlag(System.currentTimeMillis(), atomicFlag));
}
}
-
+
/** Overrides superclass method. Updates time stamp for that edit. */
@Override
public synchronized void redo() throws CannotRedoException {
@@ -1531,8 +1521,8 @@ public synchronized void redo() throws CannotRedoException {
stampFlags.put(anEdit, new StampFlag(System.currentTimeMillis(), atomicFlag));
}
}
-
- /** Method which gets time stamp of next Undoable edit to be undone.
+
+ /** Method which gets time stamp of next Undoable edit to be undone.
* @ return time stamp in milliseconds or 0 (if don't exit edit to be undone). */
public long getTimeStampOfEditToBeUndone() {
UndoableEdit nextUndo = editToBeUndone();
@@ -1542,7 +1532,7 @@ public long getTimeStampOfEditToBeUndone() {
return stampFlags.get(nextUndo).getTimeStamp();
}
}
-
+
/** Method which gets time stamp of next Undoable edit to be redone.
* @ return time stamp in milliseconds or 0 (if don't exit edit to be redone). */
public long getTimeStampOfEditToBeRedone() {
@@ -1553,8 +1543,8 @@ public long getTimeStampOfEditToBeRedone() {
return stampFlags.get(nextRedo).getTimeStamp();
}
}
-
- /** Method which gets atomic flag of next Undoable edit to be undone.
+
+ /** Method which gets atomic flag of next Undoable edit to be undone.
* @ return atomic flag in milliseconds or 0 (if don't exit edit to be undone). */
public Object getAtomicFlagOfEditToBeUndone() {
UndoableEdit nextUndo = editToBeUndone();
@@ -1564,7 +1554,7 @@ public Object getAtomicFlagOfEditToBeUndone() {
return (stampFlags.get(nextUndo)).getAtomicFlag();
}
}
-
+
/** Method which gets atomic flag of next Undoable edit to be redone.
* @ return time stamp in milliseconds or 0 (if don't exit edit to be redone). */
public Object getAtomicFlagOfEditToBeRedone() {
@@ -1575,40 +1565,40 @@ public Object getAtomicFlagOfEditToBeRedone() {
return (stampFlags.get(nextRedo)).getAtomicFlag();
}
}
-
+
} // End of inner class UndoRedoTimeStampManager.
- /** Simple nested class for storing time stamp and atomic flag used
+ /** Simple nested class for storing time stamp and atomic flag used
* in UndoRedoStampFlagManager.
*/
- static class StampFlag {
-
- /** Time stamp when was an UndoableEdit (to which is this class mapped via
+ private static class StampFlag {
+
+ /** Time stamp when was an UndoableEdit (to which is this class mapped via
* UndoRedoStampFlagManager,) was created, replaced, undone, or redone. */
private long timeStamp;
-
+
/** Atomic flag. If this object is not null it means that an UndoableEdit ( to which
- * is this class mapped via UndoRedoStampFlagManager,) was created as part of one
+ * is this class mapped via UndoRedoStampFlagManager,) was created as part of one
* action which could consist from more UndoableEdits in differrent editor supports.
* These Undoable edits are marked with this (i.e. same) object. */
- private Object atomicFlag;
-
+ private final Object atomicFlag;
+
/** Consructor. */
public StampFlag(long timeStamp, Object atomicFlag) {
this.timeStamp = timeStamp;
- this.atomicFlag = atomicFlag;
+ this.atomicFlag = atomicFlag;
}
-
+
/** Getter for time stamp. */
public long getTimeStamp() {
return timeStamp;
}
-
+
/** Setter for time stamp. */
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
-
+
/** Getter for atomic flag.
@ return Returns null if is not linked with more Undoable edits.*/
public Object getAtomicFlag() {
@@ -1624,6 +1614,7 @@ public SaveImpl(PropertiesEditorSupport des) {
this.des = des;
}
+ @Override
public void run() throws IOException {
if (des.desEnv().isModified() && des.isEnvReadOnly()) {
IOException e = new IOException("File is read-only: " + ((Environment) des.env).getFileImpl()); // NOI18N
@@ -1645,7 +1636,7 @@ public boolean equals(Object obj) {
}
private static final class PropertiesEditorLookup extends ProxyLookup {
- private Lookup initialLookup;
+ private final Lookup initialLookup;
public PropertiesEditorLookup(Lookup lookup) {
super(lookup);
this.initialLookup = lookup;
diff --git a/ide/properties/src/org/netbeans/modules/properties/PropertiesEncoding.java b/ide/properties/src/org/netbeans/modules/properties/PropertiesEncoding.java
index 5750e51a8076..0f537d7d7383 100644
--- a/ide/properties/src/org/netbeans/modules/properties/PropertiesEncoding.java
+++ b/ide/properties/src/org/netbeans/modules/properties/PropertiesEncoding.java
@@ -19,9 +19,6 @@
package org.netbeans.modules.properties;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.net.URL;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
@@ -33,17 +30,13 @@
import java.nio.charset.CoderResult;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.netbeans.modules.properties.formatter.CodeStyle;
import org.netbeans.spi.queries.FileEncodingQueryImplementation;
-import org.openide.filesystems.FileAttributeEvent;
-import org.openide.filesystems.FileChangeListener;
-import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileObject;
+
import static java.lang.Math.min;
import static java.nio.charset.CoderResult.OVERFLOW;
import static java.nio.charset.CoderResult.UNDERFLOW;
-import org.openide.filesystems.FileRenameEvent;
-import org.openide.filesystems.FileStateInvalidException;
-import org.openide.filesystems.URLMapper;
/**
*
@@ -54,153 +47,94 @@ public final class PropertiesEncoding extends FileEncodingQueryImplementation {
static final String PROP_CHARSET_NAME = "ISO-8859-1";
/*
* TO DO:
- *
+ *
* DECODER
* - leave some characters in the form of escape sequence, e.g. 0x00 - 0x1f
* - allow decoding of supplementary characters (?)
*/
-
+
@Override
public Charset getEncoding(FileObject file) {
assert !file.isValid() || file.isData();
Object attribute = file.getAttribute(PropertiesDataNode.PROPERTY_ENCODING);
- if (attribute != null) {
- boolean useProjectEncoding = (Boolean) attribute;
- if (useProjectEncoding) {
- return null;
- }
+ Boolean useProjectEncoding = null;
+ if (attribute instanceof Boolean) {
+ useProjectEncoding = (Boolean) attribute;
}
- try {
- return new PropCharset(file);
- } catch (FileStateInvalidException ex) {
+ if (useProjectEncoding == null) {
+ useProjectEncoding = CodeStyle.get(file).useProjectEncoding();
+ }
+ if (useProjectEncoding) {
return null;
}
+ return new PropCharset();
}
-
- /**
- *
- */
- static final class PropCharset extends Charset implements FileChangeListener {
- private final Reference fileRef;
- private URL fileURL;
-
- PropCharset(FileObject file) throws FileStateInvalidException {
- super(PROP_CHARSET_NAME, null); //NOI18N
- fileRef = new WeakReference(file);
- file.addFileChangeListener(this);
- updateURL(file);
- }
+ @SuppressWarnings("PackageVisibleInnerClass") // For unittests
+ static final class PropCharset extends Charset {
PropCharset() {
super(PROP_CHARSET_NAME, null); //NOI18N
- fileRef = null;
}
+ @Override
public boolean contains(Charset charset) {
return true;
}
+ @Override
public CharsetEncoder newEncoder() {
return new PropCharsetEncoder(this);
}
-
- public CharsetDecoder newDecoder() {
- long fileSize = (fileRef != null) ? getFileSize() : -1;
- return (fileSize > 0l) ? new PropCharsetDecoder(this, fileSize)
- : new PropCharsetDecoder(this);
- }
-
- private long getFileSize() {
- FileObject file = getFile();
- return ((file != null) && file.isValid()) ? file.getSize() : 0l;
- }
- private FileObject getFile() {
- FileObject fileObj = fileRef.get();
-
- URL url;
- synchronized (this) {
- url = fileURL;
- }
-
- if ((fileObj == null) && (url != null)) {
- fileObj = URLMapper.findFileObject(url);
- }
- return fileObj;
- }
-
- public void fileRenamed(FileRenameEvent fe) {
- updateURL(fe.getFile());
- }
-
- public void fileChanged(FileEvent fe) {
- updateURL(fe.getFile());
+ @Override
+ public CharsetDecoder newDecoder() {
+ return new PropCharsetDecoder(this);
}
- private synchronized void updateURL(FileObject file) {
- fileURL = file.toURL();
- }
+ }
- public void fileDeleted(FileEvent fe) { }
+ @SuppressWarnings("PackageVisibleInnerClass") // For unittests
+ static final class PropCharsetEncoder extends CharsetEncoder {
- public void fileAttributeChanged(FileAttributeEvent fe) { }
+ private static final int AVG_ENCODED_TOKEN_LEN = 3;
+ private static final int MAX_ENCODED_TOKEN_LEN = 6;
- public void fileDataCreated(FileEvent fe) {
- /* this should be never called on plain files (non-directories) */
-// assert false;
- }
+ private static final int IN_BUF_SIZE = 8192;
+ private static final int OUT_BUF_SIZE = IN_BUF_SIZE * AVG_ENCODED_TOKEN_LEN;
- public void fileFolderCreated(FileEvent fe) {
- /* this should be never called on plain files (non-directories) */
- assert false;
- }
+ private final char[] inBuf = new char[IN_BUF_SIZE];
+ private final byte[] outBuf = new byte[OUT_BUF_SIZE];
- }
-
- /**
- *
- * @author Marian Petras
- */
- static final class PropCharsetEncoder extends CharsetEncoder {
-
- private static final int avgEncodedTokenLen = 3;
- private static final int maxEncodedTokenLen = 6;
-
- private static final int inBufSize = 8192;
- private static final int outBufSize = inBufSize * avgEncodedTokenLen;
-
- private final char[] inBuf = new char[inBufSize];
- private final byte[] outBuf = new byte[outBufSize];
-
private int inBufPos, outBufPos;
-
+
private boolean emptyIn;
private boolean fullOut;
private boolean emptyInBuf;
-
+
PropCharsetEncoder(Charset charset) {
- super(charset, avgEncodedTokenLen, maxEncodedTokenLen);
+ super(charset, AVG_ENCODED_TOKEN_LEN, MAX_ENCODED_TOKEN_LEN);
}
PropCharsetEncoder() {
- super(new PropCharset(), avgEncodedTokenLen, maxEncodedTokenLen);
+ super(new PropCharset(), AVG_ENCODED_TOKEN_LEN, MAX_ENCODED_TOKEN_LEN);
}
-
+
{
implReset();
}
-
+
@Override
protected void implReset() {
inBufPos = 0;
outBufPos = 0;
-
+
emptyIn = false;
fullOut = false;
emptyInBuf = true;
}
+ @Override
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
emptyIn = false;
fullOut = false;
@@ -229,13 +163,13 @@ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
return OVERFLOW;
}
}
-
+
@Override
protected CoderResult implFlush(ByteBuffer out) {
return flushOutBuf(out) ? OVERFLOW
: UNDERFLOW;
}
-
+
/**
* Reads and stores as many characters from the input buffer as possible.
* If there are no more characters available in the input buffer,
@@ -245,44 +179,45 @@ private void readIn(CharBuffer in) {
if (emptyIn) {
return;
}
-
+
int inRemaining = in.remaining();
if (inRemaining == 0) {
emptyIn = true;
return;
}
-
+
int bufRemaining = inBuf.length - inBufPos;
if (bufRemaining == 0) {
/* no space in inBuf */
return;
}
-
+
int length = min(inRemaining, bufRemaining);
in.get(inBuf, inBufPos, length);
inBufPos += length;
emptyInBuf = false;
-
+
if (length == inRemaining) {
assert in.remaining() == 0;
emptyIn = true;
}
}
-
+
/**
* Encodes as many chars from the internal input buffer as possible.
*/
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
private void encodeBuf() {
if (emptyInBuf) {
return;
}
-
+
int encodingInBufPos = 0;
while ((encodingInBufPos < inBufPos)
- && (outBufPos <= outBufSize - maxEncodedTokenLen)) {
+ && (outBufPos <= OUT_BUF_SIZE - MAX_ENCODED_TOKEN_LEN)) {
encodeChar(inBuf[encodingInBufPos++]);
}
-
+
int remainder = inBufPos - encodingInBufPos;
if (remainder != 0) {
System.arraycopy(inBuf, encodingInBufPos,
@@ -292,11 +227,11 @@ private void encodeBuf() {
inBufPos = remainder;
emptyInBuf = (inBufPos == 0);
}
-
+
/**
* Writes as many as possible bytes from the {@code outBuf} to the given
* {@code ByteBuffer} and removes the written bytes from {@code outBuf}.
- *
+ *
* @return {@code true} if the given {@code out} buffer is overflown,
* {@code false} otherwise
*/
@@ -304,21 +239,21 @@ private boolean flushOutBuf(ByteBuffer out) {
if (fullOut) {
return true;
}
-
+
int outRemaining = out.remaining();
if (outRemaining == 0) {
fullOut = true;
return true;
}
-
+
if (outBufPos == 0) {
/* nothing to flush */
return false;
}
-
+
int length = min(outRemaining, outBufPos);
out.put(outBuf, 0, length);
-
+
int remainder = outBufPos - length;
if (remainder != 0) {
System.arraycopy(outBuf, length,
@@ -326,22 +261,25 @@ private boolean flushOutBuf(ByteBuffer out) {
remainder);
}
outBufPos = remainder;
-
+
if (length == outRemaining) {
assert out.remaining() == 0;
fullOut = true;
}
-
+
return (remainder != 0);
}
-
- private static final byte zeroByte = (byte) '0';
- private static final byte[] hexadecimalChars = UtilConvert.hexDigit;
-
+
+ private static final byte ZERO_BYTE = (byte) '0';
+ private static final byte[] hexadecimalChars = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'}; // #168629
+
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
private int encodeChar(final char c) {
final int oldPos = outBufPos;
final int cInt = (int) c;
-
+
if ((c == '\r') || (c == '\n') || (c == '\t') || (c == '\f')) {
/*
* Do not translate Space, Tab and FF characters
@@ -356,27 +294,27 @@ private int encodeChar(final char c) {
outBuf[outBufPos++] = hexadecimalChars[(cInt >> 12) & 0x000f];
outBuf[outBufPos++] = hexadecimalChars[(cInt >> 8) & 0x000f];
} else {
- outBuf[outBufPos++] = zeroByte;
- outBuf[outBufPos++] = zeroByte;
+ outBuf[outBufPos++] = ZERO_BYTE;
+ outBuf[outBufPos++] = ZERO_BYTE;
}
outBuf[outBufPos++] = hexadecimalChars[(cInt >> 4) & 0x000f];
outBuf[outBufPos++] = hexadecimalChars[cInt & 0x000f];
} else {
outBuf[outBufPos++] = (byte) c;
}
-
+
return outBufPos - oldPos;
}
-
+
byte[] encodeCharForTests(final char c) {
reset();
-
+
final int tokenLength = encodeChar(c);
byte[] result = new byte[tokenLength];
System.arraycopy(outBuf, 0, result, 0, tokenLength);
return result;
}
-
+
byte[] encodeStringForTests(final String s) throws CharacterCodingException {
ByteBuffer resultBuf = encode(CharBuffer.wrap(s));
byte[] resultBufArray = resultBuf.array();
@@ -389,14 +327,13 @@ byte[] encodeStringForTests(final String s) throws CharacterCodingException {
return result;
}
}
-
+
}
- /**
- *
- */
+
+ @SuppressWarnings("PackageVisibleInnerClass") // For unittests
static final class PropCharsetDecoder extends CharsetDecoder {
-
+
private final Logger log = Logger.getLogger(getClass().getName().replace('$', '.'));
private static enum State {
@@ -404,10 +341,10 @@ private static enum State {
BACKSLASH,
UNICODE,
}
-
- private static final float avgCharsPerByte = 1.00f;
- private static final float maxCharsPerByte = 6.00f;
- private static final int maxCharsPerByteInt = 6;
+
+ private static final float AVG_CHARS_PER_BYTE = 1.00f;
+ private static final float MAX_CHARS_PER_BYTE = 6.00f;
+ private static final int MAX_CHARS_PER_BYTE_INT = 6;
/*
* Five chars are written to the output when a malformed unicode
* sequence is detected. Unicode sequences are six bytes long;
@@ -418,42 +355,30 @@ private static enum State {
* (The sixth byte is re-read and handled in the next round
* of the decoding cycle.)
*/
-
- private static final int inBufSize = 8192;
- private static final int outBufSize = inBufSize;
-
- /** */
- private static final int SIZE_UNKNOWN = -1;
- /** size of the input file, or {@link #SIZE_UNKNOWN} if unknown */
- private long inputSize;
- /** number of input bytes decoded so far */
- private int bytesDecoded = 0;
-
- private final byte[] inBuf = new byte[inBufSize];
- private final char[] outBuf = new char[outBufSize];
-
+
+ private static final int IN_BUF_SIZE = 8192;
+ private static final int OUT_BUF_SIZE = IN_BUF_SIZE;
+
+ private final byte[] inBuf = new byte[IN_BUF_SIZE];
+ private final char[] outBuf = new char[OUT_BUF_SIZE];
+
private int inBufPos, outBufPos;
-
+
private boolean emptyIn;
private boolean fullOut;
private boolean emptyInBuf;
-
+
private State state;
private int unicodeBytesRead;
private int unicodeValue;
-
+
/** used when flushing a unicode sequence to the out buffer */
- private char[] unicodeValueChars = new char[4];
-
+ private final char[] unicodeValueChars = new char[4];
+
PropCharsetDecoder(Charset charset) {
- this(charset, SIZE_UNKNOWN);
+ super(charset, AVG_CHARS_PER_BYTE, MAX_CHARS_PER_BYTE);
}
-
- PropCharsetDecoder(Charset charset, long inputSize) {
- super(charset, avgCharsPerByte, maxCharsPerByte);
- this.inputSize = inputSize;
- }
-
+
{
implReset();
}
@@ -463,30 +388,25 @@ protected void implReset() {
log.finer("");
log.finer("implReset() called");
- inputSize = SIZE_UNKNOWN;
- bytesDecoded = 0;
-
inBufPos = 0;
outBufPos = 0;
-
+
emptyIn = false;
fullOut = false;
emptyInBuf = true;
-
+
state = State.INITIAL;
unicodeBytesRead = 0;
}
+ @Override
+ @SuppressWarnings("LoggerStringConcat") // usage is guarded by Logger#isLoggable
protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
log.finer("");
log.finer("decodeLoop() called");
- if (log.isLoggable(Level.FINEST)) {
- String inCount = String.format("%5d", in.remaining());
- String outCount = String.format("%5d", out.remaining());
- log.finest(" - input: " + inCount + " bytes");
- log.finest(" - output: " + outCount + " chars");
- }
-
+ log.finest(() -> " - input: " + String.format("%5d", in.remaining()) + " bytes");
+ log.finest(() -> " - output: " + String.format("%5d", out.remaining()) + " chars");
+
emptyIn = false;
fullOut = false;
try {
@@ -494,15 +414,11 @@ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
for (;;) {
readIn(in);
for (;;) {
- bytesDecoded += decodeBuf();
-
- // assert: if (bytesDecoded == inputSize) then (emptyIn)
- assert (bytesDecoded != inputSize) || emptyIn;
+ decodeBuf();
if (emptyInBuf && !emptyIn) {
continue readInLoop;
- } else if (emptyIn && hasPendingCharacters()
- && ((inputSize == SIZE_UNKNOWN) || (bytesDecoded >= inputSize))) {
+ } else if (emptyIn && hasPendingCharacters()) {
handlePendingCharacters();
}
flushOutBuf(out);
@@ -523,24 +439,24 @@ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
return OVERFLOW;
}
}
-
+
/**
* This is method is only necessary because of bug in JDK 1.5.x that
* {@code flush()} is not always called when it should be.
* Once JDK 1.5.x is not supported, remove this method.
- *
+ *
* @see #handlePendingCharacters()
*/
private boolean hasPendingCharacters() {
return state != State.INITIAL;
}
-
+
/**
* This is method is only necessary because of bug in JDK 1.5.x that
* {@code flush()} is not always called when it should be.
* Once JDK 1.5.x is not supported, move this method's functionality
* to method {@code implFlush()} and remove this method.
- *
+ *
* @see JDK bug 6221056
* @see JDK bug 4744247
*/
@@ -550,26 +466,24 @@ private void handlePendingCharacters() {
log.finer(" - no pending characters");
return;
}
-
+
switch (state) {
- case INITIAL:
+ case INITIAL -> {
assert false;
- break;
- case BACKSLASH:
+ }
+ case BACKSLASH -> {
log.finer(" - backslash pending");
outBuf[outBufPos++] = '\\';
- break;
- case UNICODE:
+ }
+ case UNICODE -> {
log.finer(" - broken \\u.... sequence pending");
- if (log.isLoggable(Level.FINEST)) {
- log.finest(" - " + unicodeBytesRead + " unicode value bytes pending");
- }
+ log.finest(() -> " - " + unicodeBytesRead + " unicode value bytes pending");
assert (unicodeBytesRead >= 0) && (unicodeBytesRead < 4);
flushUnicodeSequence();
- break;
- default:
+ }
+ default -> {
assert false;
- break;
+ }
}
state = State.INITIAL;
}
@@ -582,7 +496,7 @@ protected CoderResult implFlush(CharBuffer out) {
return flushOutBuf(out) ? OVERFLOW
: UNDERFLOW;
}
-
+
/**
* Reads and stores as many characters from the input buffer as possible.
* If there are no more characters available in the input buffer,
@@ -594,39 +508,39 @@ private void readIn(ByteBuffer in) {
log.finer(" - input empty (emptyIn already set)");
return;
}
-
+
int inRemaining = in.remaining();
if (inRemaining == 0) {
log.finer(" - input empty (emptyIn will be set)");
emptyIn = true;
return;
}
-
+
int bufRemaining = inBuf.length - inBufPos;
if (bufRemaining == 0) {
log.finer(" - no space remaining in inBuf");
/* no space in inBuf */
return;
}
-
+
int length = min(inRemaining, bufRemaining);
if (log.isLoggable(Level.FINER)) {
- log.finer(" - " + length + " bytes will be read");
+ log.finer(() -> " - " + length + " bytes will be read");
}
in.get(inBuf, inBufPos, length);
inBufPos += length;
emptyInBuf = false;
-
+
if (length == inRemaining) {
assert in.remaining() == 0;
log.finer(" - all remaining bytes were read (emptyIn will be set)");
emptyIn = true;
}
}
-
+
/**
* Encodes as many chars from the internal input buffer as possible.
- *
+ *
* @return number of bytes decoded
*/
private int decodeBuf() {
@@ -635,12 +549,12 @@ private int decodeBuf() {
log.finer(" - inBuf is empty - nothing to decode");
return 0;
}
-
+
int decodingInBufPos = 0;
log.finest(" - decoding bytes:");
- log.finest(" - initial state: " + state);
+ log.finest(() -> " - initial state: " + state);
while ((decodingInBufPos < inBufPos)
- && (outBufPos <= outBufSize - maxCharsPerByteInt)) {
+ && (outBufPos <= OUT_BUF_SIZE - MAX_CHARS_PER_BYTE_INT)) {
int decodedChars = decodeByte(inBuf[decodingInBufPos++]);
if (log.isLoggable(Level.FINEST)) {
StringBuilder sb = new StringBuilder(60);
@@ -663,7 +577,7 @@ private int decodeBuf() {
int remainder = inBufPos - decodingInBufPos;
if (remainder != 0) {
if (log.isLoggable(Level.FINER)) {
- log.finer(" - " + remainder + " bytes will remain in the inBuf");
+ log.finer(() -> " - " + remainder + " bytes will remain in the inBuf");
}
System.arraycopy(inBuf, decodingInBufPos,
inBuf, 0,
@@ -675,9 +589,9 @@ private int decodeBuf() {
emptyInBuf = (inBufPos == 0);
return decodingInBufPos;
}
-
+
/**
- *
+ *
* @return {@code true} if the given {@code out} buffer is overflown,
* {@code false} otherwise
*/
@@ -688,29 +602,29 @@ private boolean flushOutBuf(CharBuffer out) {
log.finer(" - outBuf is empty - nothing to flush");
return false;
}
-
+
if (fullOut) { //we know that (outBufPos != null)
log.finer(" - output CharBuffer is full (fullOut already set)");
return true;
}
-
+
int outRemaining = out.remaining();
if (outRemaining == 0) {
log.finer(" - output CharBuffer is full (fullOut will be set)");
fullOut = true;
return true;
}
-
+
int length = min(outRemaining, outBufPos);
if (log.isLoggable(Level.FINER)) {
- log.finer(" - " + length + " chars will be written");
+ log.finer(() -> " - " + length + " chars will be written");
}
out.put(outBuf, 0, length);
-
+
int remainder = outBufPos - length;
if (remainder != 0) {
if (log.isLoggable(Level.FINER)) {
- log.finer(" - " + remainder + " bytes will remain in the outBuf");
+ log.finer(() -> " - " + remainder + " bytes will remain in the outBuf");
}
System.arraycopy(outBuf, length,
outBuf, 0,
@@ -719,36 +633,36 @@ private boolean flushOutBuf(CharBuffer out) {
log.finer(" - all bytes were successfully flushed");
}
outBufPos = remainder;
-
+
if (length == outRemaining) {
assert out.remaining() == 0;
log.finer(" - output CharBuffer is now full (fullOut will be set)");
fullOut = true;
}
-
+
return (remainder != 0);
}
-
- private static final String hexadecimalChars
- = "0123456789abcdefABCDEF"; //NOI18N
-
+
+ private static final String HEXADECIMAL_CHARS = "0123456789abcdefABCDEF"; //NOI18N
+
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
private int decodeByte(final byte b) {
final int oldPos = outBufPos;
final int bInt = (b >= 0 ? b : b + 256);
assert (bInt >= 0) && ((bInt & 0xff) == bInt);
-
+
final char bChar = (char) bInt;
-
+
switch (state) {
- case INITIAL:
+ case INITIAL -> {
if (bChar == '\\') {
state = State.BACKSLASH;
} else {
outBuf[outBufPos++] = bChar;
/* keep the state at INITIAL */
}
- break;
- case BACKSLASH:
+ }
+ case BACKSLASH -> {
if (bChar == 'u') {
state = State.UNICODE;
} else {
@@ -756,10 +670,10 @@ private int decodeByte(final byte b) {
outBuf[outBufPos++] = bChar;
state = State.INITIAL;
}
- break;
- case UNICODE:
+ }
+ case UNICODE -> {
boolean malformed = false;
- int index = hexadecimalChars.indexOf(bChar);
+ int index = HEXADECIMAL_CHARS.indexOf(bChar);
if (index >= 0) {
if (index > 15) { //one of [A-F] used
index -= 6; //transform to lowercase
@@ -770,13 +684,13 @@ private int decodeByte(final byte b) {
if (unicodeValue <= 0x20) {
unicodeValueChars[3] = bChar;
/*
- * Do not translate Unicode sequences of value
- * 20h (space) or less (control characters).
- * Changing form of these unicode sequences
- * to one-character form might change
- * semantics, which is not desirable
- * (see issue #111530).
- */
+ * Do not translate Unicode sequences of value
+ * 20h (space) or less (control characters).
+ * Changing form of these unicode sequences
+ * to one-character form might change
+ * semantics, which is not desirable
+ * (see issue #111530).
+ */
flushUnicodeSequence();
} else {
outBuf[outBufPos++] = (char) unicodeValue;
@@ -789,8 +703,8 @@ private int decodeByte(final byte b) {
} else {
malformed = true;
/*
- * send the malformed unicode sequence to the output
- */
+ * send the malformed unicode sequence to the output
+ */
flushUnicodeSequence();
state = State.INITIAL;
}
@@ -801,12 +715,12 @@ private int decodeByte(final byte b) {
return -1;
}
}
- break;
- default:
+ }
+ default -> {
assert false;
- break;
+ }
}
-
+
return outBufPos - oldPos;
}
@@ -816,6 +730,7 @@ private int decodeByte(final byte b) {
* It also resets fields {@link #unicodeBytesRead}
* and {@link #unicodeValue} to {@code 0}.
*/
+ @SuppressWarnings("ValueOfIncrementOrDecrementUsed")
private void flushUnicodeSequence() {
outBuf[outBufPos++] = '\\';
outBuf[outBufPos++] = 'u';
@@ -825,15 +740,15 @@ private void flushUnicodeSequence() {
unicodeBytesRead = 0;
unicodeValue = 0;
}
-
+
private static char[] hexavalue(byte b) {
final int bInt = (b >= 0 ? b : b + 256);
char[] result = new char[2];
- result[0] = hexadecimalChars.charAt(bInt / 16);
- result[1] = hexadecimalChars.charAt(bInt % 16);
+ result[0] = HEXADECIMAL_CHARS.charAt(bInt / 16);
+ result[1] = HEXADECIMAL_CHARS.charAt(bInt % 16);
return result;
}
-
+
char[] decodeBytesForTests(final byte[] bytes) throws CharacterCodingException {
CharBuffer resultBuf = decode(ByteBuffer.wrap(bytes));
char[] resultBufArray = resultBuf.array();
@@ -846,7 +761,7 @@ char[] decodeBytesForTests(final byte[] bytes) throws CharacterCodingException {
return result;
}
}
-
+
}
}
diff --git a/ide/properties/src/org/netbeans/modules/properties/UtilConvert.java b/ide/properties/src/org/netbeans/modules/properties/UtilConvert.java
index 8d2eb94f0ca5..3f52c1dd30d9 100644
--- a/ide/properties/src/org/netbeans/modules/properties/UtilConvert.java
+++ b/ide/properties/src/org/netbeans/modules/properties/UtilConvert.java
@@ -45,223 +45,8 @@ private UtilConvert() {
public static final String strictKeyValueSeparators = "=:";
- /** Differs from JDK's implementation in that it does not save ' ' as '\ '. */
- private static final String specialSaveChars = "=:\t\r\n\f#!";
-
public static final String whiteSpaceChars = " \t\r\n\f";
-
- /**
- * Escape key value. Converts string to one with escaped ' ','=',':', and last '\\'
- * in case they are not escaped already. Used for formating user input.
- * //!!! wrong semantics what does it mean if not escaped already?
- */
- public static String escapePropertiesSpecialChars (String source) {
- return source; // prj40 trunk compatability
-// if(source == null) return null;
-// StringBuffer result = new StringBuffer();
-// for(int i=0; i0 && source.charAt(i-1) != '\\'))
-// result.append('\\');
-// }
-// // last char == '\\'
-// if(i==source.length()-1 && x == '\\') {
-// if( i>0 && source.charAt(i-1)!='\\')
-// result.append('\\');
-// }
-// result.append(x);
-// }
-// return result.toString();
- }
-
- /** Checks whether the string contains only spaces */
- private static boolean onlySpaces(String s){
- for (int i = 0; i1 && source.charAt(source.length()-2)!='\\')
-// return new String(new StringBuffer(source).append('\\'));
-// }
-// return source;
- }
-
- /**
- * Converts these java special chars ('\t', '\n', '\b', '\r', '\f') to encoded escapes.
- * Note there are not converted unicode chars.
- */
- public static String escapeJavaSpecialChars(String source) {
- return source; // prj40 trunk compatability
-// if(source == null) return null;
-// StringBuffer result = new StringBuffer();
-// for (int i=0; i interpret as a normal char
-// }
-// } else
-// outBuffer.append(aChar);
-// }
-// return outBuffer.toString();
- }
-
- /**
- * Convert chars to encoded '\\uxxxx' using comment escaping rules.
- * @param commentString
- * @return escaped comment
- */
- public static String escapeComment(String commentString) {
- return charsToUnicodes(commentString, true);
- }
-
- /**
- * Converts chars to encoded '\\uxxxx'.
- * Note there are not converted '\\"', '\\'', '\\ ', '\\\\' and java special chars escapes.
- */
- public static String charsToUnicodes(String s){
- return charsToUnicodes(s, false);
- }
-
-
- /**
- * Converts chars to encoded '\\uxxxx'. If skipWhiteSpaces is true, then white spaces won't be converted
- * Note there are not converted '\\"', '\\'', '\\ ', '\\\\' and java special chars escapes.
- */
- public static String charsToUnicodes(String theString, boolean skipWhiteSpaces) {
- return theString; // prj40 trunk compatability
-// if(theString == null) return null;
-// char aChar;
-// int len = theString.length();
-// StringBuffer outBuffer = new StringBuffer(len*2);
-//
-// for(int x=0; x 127) ) {
-//
-// if (skipWhiteSpaces && Character.isWhitespace(aChar)){
-// // do not convert white spaces
-// outBuffer.append(aChar);
-// continue;
-// }
-//
-// outBuffer.append('\\');
-// outBuffer.append('u');
-// outBuffer.append(toHex((aChar >> 12) & 0xF));
-// outBuffer.append(toHex((aChar >> 8) & 0xF));
-// outBuffer.append(toHex((aChar >> 4) & 0xF));
-// outBuffer.append(toHex((aChar >> 0) & 0xF));
-// } else {
-// outBuffer.append(aChar);
-// }
-// }
-// return outBuffer.toString();
- }
-
-
/**
* Converts encoded \\uxxxx to unicode chars
* and changes special saved chars to their original forms
@@ -329,58 +114,4 @@ public static String loadConvert (String theString) {
return outBuffer.toString();
}
- /**
- * Converts unicodes to encoded \\uxxxx
- * and writes out any of the characters in specialSaveChars
- * with a preceding slash.
- * Differs from Sun's implementation in that it does not save ' ' as '\ '.
- */
- public static String saveConvert(String theString) {
- char aChar;
- int len = theString.length();
- StringBuffer outBuffer = new StringBuffer(len*2);
-
- for(int x=0; x 127)) {
- outBuffer.append('\\');
- outBuffer.append('u');
- outBuffer.append(toHex((aChar >> 12) & 0xF));
- outBuffer.append(toHex((aChar >> 8) & 0xF));
- outBuffer.append(toHex((aChar >> 4) & 0xF));
- outBuffer.append(toHex((aChar >> 0) & 0xF));
- } else {
- if (specialSaveChars.indexOf(aChar) != -1)
- outBuffer.append('\\');
- outBuffer.append(aChar);
- }
- }
- }
- return outBuffer.toString();
- }
-
- /**
- * Convert a nibble to a hex character
- * @param nibble the nibble to convert.
- */
- private static char toHex(int nibble) {
- return (char)hexDigit[(nibble & 0xF)];
- }
-
- /** A table of hex digits */
- static final byte[] hexDigit = {
- '0','1','2','3','4','5','6','7','8','9',
- 'a','b','c','d','e','f'}; // #168629
}
diff --git a/ide/properties/src/org/netbeans/modules/properties/formatter/Bundle.properties b/ide/properties/src/org/netbeans/modules/properties/formatter/Bundle.properties
new file mode 100644
index 000000000000..df91ff627983
--- /dev/null
+++ b/ide/properties/src/org/netbeans/modules/properties/formatter/Bundle.properties
@@ -0,0 +1,37 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+AN_Preview=Preview
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+FmtEncoding.useProjectEncodingCB.text=Use project encoding
+FmtEncoding.useProjectEncodingCB.info=Disables automatic native2ascii conversion
+FmtWrapping.AccessibleContext.accessibleName=
+FmtEncoding.name=Encoding
diff --git a/ide/properties/src/org/netbeans/modules/properties/formatter/CodeStyle.java b/ide/properties/src/org/netbeans/modules/properties/formatter/CodeStyle.java
new file mode 100644
index 000000000000..1dc510781b0a
--- /dev/null
+++ b/ide/properties/src/org/netbeans/modules/properties/formatter/CodeStyle.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.properties.formatter;
+
+import java.util.prefs.Preferences;
+
+import javax.swing.text.Document;
+import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
+import org.openide.filesystems.FileObject;
+
+import static org.netbeans.modules.properties.formatter.FmtOptions.expandTabToSpaces;
+import static org.netbeans.modules.properties.formatter.FmtOptions.indentSize;
+import static org.netbeans.modules.properties.formatter.FmtOptions.rightMargin;
+import static org.netbeans.modules.properties.formatter.FmtOptions.spacesPerTab;
+import static org.netbeans.modules.properties.formatter.FmtOptions.tabSize;
+import static org.netbeans.modules.properties.formatter.FmtOptions.useProjectEncoding;
+
+/**
+ * Adapted from CodeStyle in Javascript2 Editor
+ */
+public final class CodeStyle {
+
+ private final Preferences preferences;
+
+ private CodeStyle(Preferences preferences) {
+ this.preferences = preferences;
+ }
+
+ public static CodeStyle get(Document doc) {
+ return new CodeStyle(CodeStylePreferences.get(doc).getPreferences());
+ }
+
+ public static CodeStyle get(FileObject doc) {
+ return new CodeStyle(CodeStylePreferences.get(doc).getPreferences());
+ }
+
+ // General tabs and indents ------------------------------------------------
+
+ public boolean expandTabToSpaces() {
+ return preferences.getBoolean(expandTabToSpaces, FmtOptions.getDefaultAsBoolean(expandTabToSpaces));
+ }
+
+ public int getTabSize() {
+ return preferences.getInt(tabSize, FmtOptions.getDefaultAsInt(tabSize));
+ }
+
+ public int getIndentSize() {
+ return preferences.getInt(indentSize, FmtOptions.getDefaultAsInt(indentSize));
+ }
+
+ public int getSpacesPerTab() {
+ return preferences.getInt(spacesPerTab, FmtOptions.getDefaultAsInt(spacesPerTab));
+ }
+
+ public int getRightMargin() {
+ return preferences.getInt(rightMargin, FmtOptions.getDefaultAsInt(rightMargin));
+ }
+
+ public boolean useProjectEncoding() {
+ return preferences.getBoolean(useProjectEncoding, FmtOptions.getDefaultAsBoolean(useProjectEncoding));
+ }
+
+}
diff --git a/ide/properties/src/org/netbeans/modules/properties/formatter/FmtEncoding.form b/ide/properties/src/org/netbeans/modules/properties/formatter/FmtEncoding.form
new file mode 100644
index 000000000000..a670ea70316f
--- /dev/null
+++ b/ide/properties/src/org/netbeans/modules/properties/formatter/FmtEncoding.form
@@ -0,0 +1,89 @@
+
+
+
+
+
diff --git a/ide/properties/src/org/netbeans/modules/properties/formatter/FmtEncoding.java b/ide/properties/src/org/netbeans/modules/properties/formatter/FmtEncoding.java
new file mode 100644
index 000000000000..e994ad5ddc9b
--- /dev/null
+++ b/ide/properties/src/org/netbeans/modules/properties/formatter/FmtEncoding.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.properties.formatter;
+
+
+import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
+import org.netbeans.modules.properties.formatter.FmtOptions.CategorySupport;
+
+import static org.netbeans.modules.properties.formatter.FmtOptions.CategorySupport.OPTION_ID;
+import static org.netbeans.modules.properties.formatter.FmtOptions.useProjectEncoding;
+
+
+public class FmtEncoding extends javax.swing.JPanel {
+
+ /** Creates new form FmtEncoding */
+ @SuppressWarnings("LeakingThisInConstructor")
+ public FmtEncoding() {
+ initComponents();
+
+ useProjectEncodingCB.putClientProperty(OPTION_ID, useProjectEncoding);
+ }
+
+ public static PreferencesCustomizer.Factory getController() {
+ String preview = """
+ # Comment
+ key1.title=Demo Title
+ key2.title=Unicode symbols can be encoded to ASCII
+ """;
+
+ return new CategorySupport.Factory("encoding", FmtEncoding.class, preview);//NOI18N
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ useProjectEncodingCB = new javax.swing.JCheckBox();
+ jLabel1 = new javax.swing.JLabel();
+
+ setName(org.openide.util.NbBundle.getMessage(FmtEncoding.class, "FmtEncoding.name")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(useProjectEncodingCB, org.openide.util.NbBundle.getMessage(FmtEncoding.class, "FmtEncoding.useProjectEncodingCB.text")); // NOI18N
+ useProjectEncodingCB.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ useProjectEncodingCBActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FmtEncoding.class, "FmtEncoding.useProjectEncodingCB.info")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(21, 21, 21)
+ .addComponent(jLabel1))
+ .addComponent(useProjectEncodingCB))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(useProjectEncodingCB)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel1)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ private void useProjectEncodingCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useProjectEncodingCBActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_useProjectEncodingCBActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JCheckBox useProjectEncodingCB;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/ide/properties/src/org/netbeans/modules/properties/formatter/FmtOptions.java b/ide/properties/src/org/netbeans/modules/properties/formatter/FmtOptions.java
new file mode 100644
index 000000000000..1caf1cb0bb7e
--- /dev/null
+++ b/ide/properties/src/org/netbeans/modules/properties/formatter/FmtOptions.java
@@ -0,0 +1,599 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.properties.formatter;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.prefs.AbstractPreferences;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+import javax.swing.ComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import org.netbeans.api.editor.document.AtomicLockDocument;
+import org.netbeans.api.editor.document.LineDocumentUtils;
+import org.netbeans.api.editor.settings.SimpleValueNames;
+import org.netbeans.modules.editor.indent.api.Reformat;
+import org.netbeans.modules.options.editor.spi.PreferencesCustomizer;
+import org.netbeans.modules.options.editor.spi.PreviewProvider;
+import org.openide.text.CloneableEditorSupport;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author phrebejk
+ *
+ */
+public class FmtOptions {
+
+ private static final Logger LOGGER = Logger.getLogger(FmtOptions.class.getName());
+
+ public static final String expandTabToSpaces = SimpleValueNames.EXPAND_TABS;
+ public static final String tabSize = SimpleValueNames.TAB_SIZE;
+ public static final String spacesPerTab = SimpleValueNames.SPACES_PER_TAB;
+ public static final String indentSize = SimpleValueNames.INDENT_SHIFT_WIDTH;
+ public static final String rightMargin = SimpleValueNames.TEXT_LIMIT_WIDTH;
+ public static final String useProjectEncoding = "useProjectEncoding"; //NOI18N
+
+
+ private FmtOptions() {}
+
+ public static int getDefaultAsInt(String key) {
+ return Integer.parseInt(defaults.get(key));
+ }
+
+ public static boolean getDefaultAsBoolean(String key) {
+ return Boolean.parseBoolean(defaults.get(key));
+ }
+
+ public static String getDefaultAsString(String key) {
+ return defaults.get(key);
+ }
+
+ // Private section ---------------------------------------------------------
+
+ private static final String TRUE = "true"; // NOI18N
+ private static final String FALSE = "false"; // NOI18N
+
+
+ private static Map defaults;
+
+ static {
+ createDefaults();
+ }
+
+ private static void createDefaults() {
+ String defaultValues[][] = {
+ { expandTabToSpaces, TRUE}, //NOI18N
+ { tabSize, "8"}, //NOI18N
+ { indentSize, "4"}, //NOI18N
+ { useProjectEncoding, "true"}, //NOI18N
+ { rightMargin, "80"}, //NOI18N
+ };
+
+ defaults = new HashMap<>();
+
+ for (java.lang.String[] strings : defaultValues) {
+ defaults.put(strings[0], strings[1]);
+ }
+
+ }
+
+ // Support section ---------------------------------------------------------
+
+ public static class CategorySupport implements ActionListener, DocumentListener, PreviewProvider, PreferencesCustomizer {
+
+ public static final String OPTION_ID = "org.netbeans.modules.properties.formatter.FormatingOptions.ID";
+
+ private static final int LOAD = 0;
+ private static final int STORE = 1;
+ private static final int ADD_LISTENERS = 2;
+
+ private final String previewText;
+ private final String id;
+ protected final JPanel panel;
+ private final List components = new LinkedList<>();
+ private JEditorPane previewPane;
+
+ private final Preferences preferences;
+ private final Preferences previewPrefs;
+
+ protected CategorySupport(Preferences preferences, String id,
+ JPanel panel, String previewText, String[]... forcedOptions) {
+ this.preferences = preferences;
+ this.id = id;
+ this.panel = panel;
+ this.previewText = previewText != null ? previewText : NbBundle.getMessage(FmtOptions.class, "SAMPLE_Default"); //NOI18N
+
+ // Scan the panel for its components
+ scan(panel, components);
+
+ // Initialize the preview preferences
+ Preferences forcedPrefs = new PreviewPreferences();
+ for (String[] option : forcedOptions) {
+ forcedPrefs.put( option[0], option[1]);
+ }
+ this.previewPrefs = new ProxyPreferences(preferences, forcedPrefs);
+
+ // Load and hook up all the components
+ loadFrom(preferences);
+ addListeners();
+ }
+
+ protected void addListeners() {
+ scan(ADD_LISTENERS, null);
+ }
+
+ protected void loadFrom(Preferences preferences) {
+// loaded = true;
+ scan(LOAD, preferences);
+// loaded = false;
+ }
+//
+// public void applyChanges() {
+// storeTo(preferences);
+// }
+//
+ protected void storeTo(Preferences p) {
+ scan(STORE, p);
+ }
+
+ public void notifyChanged() {
+// if (loaded)
+// return;
+ storeTo(preferences);
+ refreshPreview();
+ }
+
+ // ActionListener implementation ---------------------------------------
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ notifyChanged();
+ }
+
+ // DocumentListener implementation -------------------------------------
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ notifyChanged();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ notifyChanged();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ notifyChanged();
+ }
+
+ // PreviewProvider methods -----------------------------------------------------
+
+ @Override
+ public JComponent getPreviewComponent() {
+ if (previewPane == null) {
+ previewPane = new JEditorPane();
+ previewPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(FmtOptions.class, "AN_Preview")); //NOI18N
+ previewPane.setEditorKit(CloneableEditorSupport.getEditorKit("text/x-properties"));
+ previewPane.setEditable(false);
+ }
+ return previewPane;
+ }
+
+ @Override
+ public void refreshPreview() {
+ JEditorPane pane = (JEditorPane) getPreviewComponent();
+ try {
+ int rm = previewPrefs.getInt(rightMargin, getDefaultAsInt(rightMargin));
+ pane.putClientProperty("TextLimitLine", rm); //NOI18N
+ }
+ catch( NumberFormatException e ) {
+ // Ignore it
+ }
+
+ Rectangle visibleRectangle = pane.getVisibleRect();
+ pane.setText(previewText);
+ pane.setIgnoreRepaint(true);
+
+ final Document doc = pane.getDocument();
+ final AtomicLockDocument ald = LineDocumentUtils.as(doc, AtomicLockDocument.class);
+ if (ald != null) {
+ final Reformat reformat = Reformat.get(doc);
+ reformat.lock();
+ try {
+ ald.runAtomic(() -> {
+ try {
+ reformat.reformat(0, doc.getLength());
+ } catch (BadLocationException ble) {
+ LOGGER.log(Level.WARNING, null, ble);
+ }
+ });
+ } finally {
+ reformat.unlock();
+ }
+ } else {
+ LOGGER.warning(String.format("Can't format %s; it's not BaseDocument.", doc)); //NOI18N
+ }
+ pane.setIgnoreRepaint(false);
+ pane.scrollRectToVisible(visibleRectangle);
+ pane.repaint(100);
+
+ }
+
+ // PreferencesCustomizer implementation --------------------------------
+
+ @Override
+ public JComponent getComponent() {
+ return panel;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return panel.getName();
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return null;
+ }
+
+ // PreferencesCustomizer.Factory implementation ------------------------
+
+ public static final class Factory implements PreferencesCustomizer.Factory {
+
+ private final String id;
+ private final Class extends JPanel> panelClass;
+ private final String previewText;
+ private final String[][] forcedOptions;
+
+ public Factory(String id, Class extends JPanel> panelClass,
+ String previewText, String[]... forcedOptions) {
+ this.id = id;
+ this.panelClass = panelClass;
+ this.previewText = previewText;
+ this.forcedOptions = forcedOptions;
+ }
+
+ @Override
+ public PreferencesCustomizer create(Preferences preferences) {
+ try {
+ return new CategorySupport(preferences, id, panelClass.getDeclaredConstructor().newInstance(), previewText, forcedOptions);
+ } catch (RuntimeException | ReflectiveOperationException e) {
+ LOGGER.log(Level.WARNING, "Exception during creating formatter customiezer", e);
+ return null;
+ }
+ }
+ } // End of CategorySupport.Factory class
+
+ // Private methods -----------------------------------------------------
+
+ private void performOperation(int operation, JComponent jc, String optionID, Preferences p) {
+ switch (operation) {
+ case LOAD:
+ loadData(jc, optionID, p);
+ break;
+ case STORE:
+ storeData(jc, optionID, p);
+ break;
+ case ADD_LISTENERS:
+ addListener(jc);
+ break;
+ default:
+ LOGGER.log(Level.WARNING, "Unknown operation value {0}", operation);
+ break;
+ }
+ }
+
+ private void scan(int what, Preferences p ) {
+ for (JComponent jc : components) {
+ Object o = jc.getClientProperty(OPTION_ID);
+ if (o instanceof String) {
+ performOperation(what, jc, (String)o, p);
+ } else if (o instanceof String[]) {
+ for(String oid : (String[])o) {
+ performOperation(what, jc, oid, p);
+ }
+ }
+ }
+ }
+
+ private void scan(Container container, List components) {
+ for (Component c : container.getComponents()) {
+ if (c instanceof JComponent) {
+ JComponent jc = (JComponent)c;
+ Object o = jc.getClientProperty(OPTION_ID);
+ if (o instanceof String || o instanceof String[])
+ components.add(jc);
+ }
+ if (c instanceof Container)
+ scan((Container)c, components);
+ }
+ }
+
+ /** Very smart method which tries to set the values in the components correctly
+ */
+ private void loadData( JComponent jc, String optionID, Preferences node ) {
+
+ if ( jc instanceof JTextField ) {
+ JTextField field = (JTextField)jc;
+ field.setText( node.get(optionID, getDefaultAsString(optionID)) );
+ }
+ else if ( jc instanceof JCheckBox ) {
+ JCheckBox checkBox = (JCheckBox)jc;
+ boolean df = getDefaultAsBoolean(optionID);
+ checkBox.setSelected( node.getBoolean(optionID, df));
+ }
+
+ }
+
+ private void storeData( JComponent jc, String optionID, Preferences node ) {
+
+ if ( jc instanceof JTextField ) {
+ JTextField field = (JTextField)jc;
+
+ String text = field.getText();
+
+ // XXX test for numbers
+ if ( isInteger(optionID) ) {
+ try {
+ Integer.parseInt(text);
+ } catch (NumberFormatException e) {
+ return;
+ }
+ }
+
+ // XXX: watch out, tabSize, spacesPerTab, indentSize and expandTabToSpaces
+ // fall back on getGlopalXXX() values and not getDefaultAsXXX value,
+ // which is why we must not remove them. Proper solution would be to
+ // store formatting preferences to MimeLookup and not use NbPreferences.
+ // The problem currently is that MimeLookup based Preferences do not support subnodes.
+ if (!optionID.equals(tabSize) &&
+ !optionID.equals(spacesPerTab) && !optionID.equals(indentSize) &&
+ getDefaultAsString(optionID).equals(text)
+ ) {
+ node.remove(optionID);
+ } else {
+ node.put(optionID, text);
+ }
+ }
+ else if ( jc instanceof JCheckBox ) {
+ JCheckBox checkBox = (JCheckBox)jc;
+ if (!optionID.equals(expandTabToSpaces) && getDefaultAsBoolean(optionID) == checkBox.isSelected())
+ node.remove(optionID);
+ else
+ node.putBoolean(optionID, checkBox.isSelected());
+ }
+ else if ( jc instanceof JComboBox) {
+ JComboBox cb = (JComboBox)jc;
+ ComboItem comboItem = ((ComboItem) cb.getSelectedItem());
+ String value = comboItem == null ? getDefaultAsString(optionID) : comboItem.value;
+
+ if (getDefaultAsString(optionID).equals(value))
+ node.remove(optionID);
+ else
+ node.put(optionID,value);
+ }
+ }
+
+ private void addListener( JComponent jc ) {
+ if ( jc instanceof JTextField ) {
+ JTextField field = (JTextField)jc;
+ field.addActionListener(this);
+ field.getDocument().addDocumentListener(this);
+ }
+ else if ( jc instanceof JCheckBox ) {
+ JCheckBox checkBox = (JCheckBox)jc;
+ checkBox.addActionListener(this);
+ }
+ else if ( jc instanceof JComboBox) {
+ JComboBox cb = (JComboBox)jc;
+ cb.addActionListener(this);
+ }
+ }
+
+
+ private static ComboItem whichItem(String value, ComboBoxModel model) {
+
+ for (int i = 0; i < model.getSize(); i++) {
+ ComboItem item = (ComboItem)model.getElementAt(i);
+ if ( value.equals(item.value)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private static class ComboItem {
+
+ String value;
+ String displayName;
+
+ public ComboItem(String value, String key) {
+ this.value = value;
+ this.displayName = NbBundle.getMessage(FmtOptions.class, key);
+ }
+
+ @Override
+ public String toString() {
+ return displayName;
+ }
+
+ }
+ }
+
+ public static class PreviewPreferences extends AbstractPreferences {
+
+ private final Map map = new HashMap<>();
+
+ public PreviewPreferences() {
+ super(null, ""); // NOI18N
+ }
+
+ @Override
+ protected void putSpi(String key, String value) {
+ map.put(key, value);
+ }
+
+ @Override
+ protected String getSpi(String key) {
+ return (String)map.get(key);
+ }
+
+ @Override
+ protected void removeSpi(String key) {
+ map.remove(key);
+ }
+
+ @Override
+ protected void removeNodeSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected String[] keysSpi() throws BackingStoreException {
+ String array[] = new String[map.keySet().size()];
+ return map.keySet().toArray( array );
+ }
+
+ @Override
+ protected String[] childrenNamesSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected AbstractPreferences childSpi(String name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected void syncSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected void flushSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ }
+
+ // read-only, no subnodes
+ public static final class ProxyPreferences extends AbstractPreferences {
+
+ private final Preferences[] delegates;
+
+ public ProxyPreferences(Preferences... delegates) {
+ super(null, ""); // NOI18N
+ this.delegates = delegates;
+ }
+
+ @Override
+ protected void putSpi(String key, String value) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected String getSpi(String key) {
+ for(Preferences p : delegates) {
+ String value = p.get(key, null);
+ if (value != null) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void removeSpi(String key) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected void removeNodeSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected String[] keysSpi() throws BackingStoreException {
+ Set keys = new HashSet<>();
+ for(Preferences p : delegates) {
+ keys.addAll(Arrays.asList(p.keys()));
+ }
+ return keys.toArray(new String[0]);
+ }
+
+ @Override
+ protected String[] childrenNamesSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected AbstractPreferences childSpi(String name) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected void syncSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ protected void flushSpi() throws BackingStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+ } // End of ProxyPreferences class
+
+ public static boolean isInteger(String optionID) {
+ String value = defaults.get(optionID);
+
+ try {
+ Integer.parseInt(value);
+ return true;
+ } catch (NumberFormatException numberFormatException) {
+ return false;
+ }
+ }
+}
diff --git a/ide/properties/test/unit/src/org/netbeans/modules/properties/ElementTest.java b/ide/properties/test/unit/src/org/netbeans/modules/properties/ElementTest.java
index ba0fb37aa914..2967706fc8f6 100644
--- a/ide/properties/test/unit/src/org/netbeans/modules/properties/ElementTest.java
+++ b/ide/properties/test/unit/src/org/netbeans/modules/properties/ElementTest.java
@@ -105,7 +105,7 @@ public void testEscapeSpecialCharsInKey() throws Exception {
checkTranslation("\u0005", "\\u0005");
checkTranslation("\u0006", "\\u0006");
checkTranslation("\u0007", "\\u0007");
- checkTranslation("\b", "\\b");
+ checkTranslation("\b", "\\u0008");
checkTranslation("\t", "\\t");
checkTranslation("\n", "\\n");
checkTranslation("\u000b", "\\u000b");
diff --git a/ide/properties/test/unit/src/org/netbeans/modules/properties/PropertiesEncodingTest.java b/ide/properties/test/unit/src/org/netbeans/modules/properties/PropertiesEncodingTest.java
index 363771c3ed20..5cc9700bac97 100644
--- a/ide/properties/test/unit/src/org/netbeans/modules/properties/PropertiesEncodingTest.java
+++ b/ide/properties/test/unit/src/org/netbeans/modules/properties/PropertiesEncodingTest.java
@@ -54,7 +54,7 @@ public void testEncodingOfSingleChar() {
compare(encoder.encodeCharForTests((char) 0x01),
new byte[] {'\\', 'u', '0', '0', '0', '1'});
compare(encoder.encodeCharForTests((char) 0x0b),
- new byte[] {'\\', 'u', '0', '0', '0', 'B'});
+ new byte[] {'\\', 'u', '0', '0', '0', 'b'});
compare(encoder.encodeCharForTests((char) 0x19),
new byte[] {'\\', 'u', '0', '0', '1', '9'});
compare(encoder.encodeCharForTests((char) 0x20),
@@ -76,39 +76,39 @@ public void testEncodingOfSingleChar() {
compare(encoder.encodeCharForTests((char) 0x7e),
new byte[] {'~'});
compare(encoder.encodeCharForTests((char) 0x7f),
- new byte[] {'\\', 'u', '0', '0', '7', 'F'});
+ new byte[] {'\\', 'u', '0', '0', '7', 'f'});
compare(encoder.encodeCharForTests((char) 0x81),
new byte[] {'\\', 'u', '0', '0', '8', '1'});
compare(encoder.encodeCharForTests((char) 0x89),
new byte[] {'\\', 'u', '0', '0', '8', '9'});
compare(encoder.encodeCharForTests((char) 0x8f),
- new byte[] {'\\', 'u', '0', '0', '8', 'F'});
+ new byte[] {'\\', 'u', '0', '0', '8', 'f'});
compare(encoder.encodeCharForTests((char) 0x90),
new byte[] {'\\', 'u', '0', '0', '9', '0'});
compare(encoder.encodeCharForTests((char) 0xa0),
- new byte[] {'\\', 'u', '0', '0', 'A', '0'});
+ new byte[] {'\\', 'u', '0', '0', 'a', '0'});
compare(encoder.encodeCharForTests((char) 0xad),
- new byte[] {'\\', 'u', '0', '0', 'A', 'D'});
+ new byte[] {'\\', 'u', '0', '0', 'a', 'd'});
compare(encoder.encodeCharForTests((char) 0xcb),
- new byte[] {'\\', 'u', '0', '0', 'C', 'B'});
+ new byte[] {'\\', 'u', '0', '0', 'c', 'b'});
compare(encoder.encodeCharForTests((char) 0xd6),
- new byte[] {'\\', 'u', '0', '0', 'D', '6'});
+ new byte[] {'\\', 'u', '0', '0', 'd', '6'});
compare(encoder.encodeCharForTests((char) 0xec),
- new byte[] {'\\', 'u', '0', '0', 'E', 'C'});
+ new byte[] {'\\', 'u', '0', '0', 'e', 'c'});
compare(encoder.encodeCharForTests((char) 0xf0),
- new byte[] {'\\', 'u', '0', '0', 'F', '0'});
+ new byte[] {'\\', 'u', '0', '0', 'f', '0'});
compare(encoder.encodeCharForTests((char) 0xfd),
- new byte[] {'\\', 'u', '0', '0', 'F', 'D'});
+ new byte[] {'\\', 'u', '0', '0', 'f', 'd'});
compare(encoder.encodeCharForTests((char) 0xfe),
- new byte[] {'\\', 'u', '0', '0', 'F', 'E'});
+ new byte[] {'\\', 'u', '0', '0', 'f', 'e'});
compare(encoder.encodeCharForTests((char) 0xff),
- new byte[] {'\\', 'u', '0', '0', 'F', 'F'});
+ new byte[] {'\\', 'u', '0', '0', 'f', 'f'});
compare(encoder.encodeCharForTests((char) 0x0100),
new byte[] {'\\', 'u', '0', '1', '0', '0'});
compare(encoder.encodeCharForTests((char) 0x0101),
new byte[] {'\\', 'u', '0', '1', '0', '1'});
compare(encoder.encodeCharForTests((char) 0x016e),
- new byte[] {'\\', 'u', '0', '1', '6', 'E'});
+ new byte[] {'\\', 'u', '0', '1', '6', 'e'});
compare(encoder.encodeCharForTests((char) 0x0777),
new byte[] {'\\', 'u', '0', '7', '7', '7'});
compare(encoder.encodeCharForTests((char) 0x0778),
@@ -116,19 +116,19 @@ public void testEncodingOfSingleChar() {
compare(encoder.encodeCharForTests((char) 0x0877),
new byte[] {'\\', 'u', '0', '8', '7', '7'});
compare(encoder.encodeCharForTests((char) 0x0a46),
- new byte[] {'\\', 'u', '0', 'A', '4', '6'});
+ new byte[] {'\\', 'u', '0', 'a', '4', '6'});
compare(encoder.encodeCharForTests((char) 0x774d),
- new byte[] {'\\', 'u', '7', '7', '4', 'D'});
+ new byte[] {'\\', 'u', '7', '7', '4', 'd'});
compare(encoder.encodeCharForTests((char) 0x8000),
new byte[] {'\\', 'u', '8', '0', '0', '0'});
compare(encoder.encodeCharForTests((char) 0x8800),
new byte[] {'\\', 'u', '8', '8', '0', '0'});
compare(encoder.encodeCharForTests((char) 0xabcd),
- new byte[] {'\\', 'u', 'A', 'B', 'C', 'D'});
+ new byte[] {'\\', 'u', 'a', 'b', 'c', 'd'});
compare(encoder.encodeCharForTests((char) 0xfffe),
- new byte[] {'\\', 'u', 'F', 'F', 'F', 'E'});
+ new byte[] {'\\', 'u', 'f', 'f', 'f', 'e'});
compare(encoder.encodeCharForTests((char) 0xffff),
- new byte[] {'\\', 'u', 'F', 'F', 'F', 'F'});
+ new byte[] {'\\', 'u', 'f', 'f', 'f', 'f'});
}
public void testEncodingOfString() throws CharacterCodingException {
@@ -163,42 +163,43 @@ public void testDecodingOfSingleChar() throws CharacterCodingException {
new char[] {'\\', 'n'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'r'}), /* CR */
new char[] {'\\', 'r'});
+ // For byte values 0-0x20 see issue #111530
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '0'}),
- new char[] {(char) 0x00});
+ new char[] {'\\', 'u', '0', '0', '0', '0'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '1'}),
- new char[] {(char) 0x01});
+ new char[] {'\\', 'u', '0', '0', '0', '1'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '2'}),
- new char[] {(char) 0x02});
+ new char[] {'\\', 'u', '0', '0', '0', '2'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '3'}),
- new char[] {(char) 0x03});
+ new char[] {'\\', 'u', '0', '0', '0', '3'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '4'}),
- new char[] {(char) 0x04});
+ new char[] {'\\', 'u', '0', '0', '0', '4'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '5'}),
- new char[] {(char) 0x05});
+ new char[] {'\\', 'u', '0', '0', '0', '5'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '6'}),
- new char[] {(char) 0x06});
+ new char[] {'\\', 'u', '0', '0', '0', '6'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '7'}),
- new char[] {(char) 0x07});
+ new char[] {'\\', 'u', '0', '0', '0', '7'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '8'}),
- new char[] {(char) 0x08});
+ new char[] {'\\', 'u', '0', '0', '0', '8'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', '9'}),
- new char[] {'\\', 'u', '0', '0', '0', '9'}); //see issue #111530
+ new char[] {'\\', 'u', '0', '0', '0', '9'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', 'a'}),
- new char[] {'\n'});
+ new char[] {'\\', 'u', '0', '0', '0', 'a'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', 'b'}),
- new char[] {(char) 0x0b});
+ new char[] {'\\', 'u', '0', '0', '0', 'b'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', 'c'}),
- new char[] {'\\', 'u', '0', '0', '0', 'c'}); //see issue #111530
+ new char[] {'\\', 'u', '0', '0', '0', 'c'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', 'd'}),
- new char[] {'\r'});
+ new char[] {'\\', 'u', '0', '0', '0', 'd'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', 'e'}),
- new char[] {(char) 0x0e});
+ new char[] {'\\', 'u', '0', '0', '0', 'e'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '0', 'f'}),
- new char[] {(char) 0x0f});
+ new char[] {'\\', 'u', '0', '0', '0', 'f'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '1', '9'}),
- new char[] {(char) 0x19});
+ new char[] {'\\', 'u', '0', '0', '1', '9'});
compare(decoder.decodeBytesForTests(new byte[] {'\\', 'u', '0', '0', '2', '0'}),
- new char[] {'\\', 'u', '0', '0', '2', '0'}); //see issue #111530
+ new char[] {'\\', 'u', '0', '0', '2', '0'});
compare(decoder.decodeBytesForTests(new byte[] {' '}),
new char[] {(char) 0x20});
compare(decoder.decodeBytesForTests(new byte[] {'!'}),
diff --git a/java/i18n/src/org/netbeans/modules/i18n/java/JavaI18nFinder.java b/java/i18n/src/org/netbeans/modules/i18n/java/JavaI18nFinder.java
index 5dd8ab510e8e..201095485d13 100644
--- a/java/i18n/src/org/netbeans/modules/i18n/java/JavaI18nFinder.java
+++ b/java/i18n/src/org/netbeans/modules/i18n/java/JavaI18nFinder.java
@@ -565,13 +565,11 @@ private String extractString(String sourceString) {
* @return true if string is internationalized and i18nSearch flag is true
* or if if string is non-internationalized and i18nSearch flag is false */
protected boolean isSearchedString(String partHardLine, String hardString) {
- String lineToMatch = UtilConvert.unicodesToChars(partHardLine);
-
Boolean regexpTestResult;
Exception ex = null;
try {
String regexp = createRegularExpression(hardString);
- regexpTestResult = (Pattern.compile(regexp).matcher(lineToMatch).find()
+ regexpTestResult = (Pattern.compile(regexp).matcher(partHardLine).find()
== i18nSearch); //auto-boxing
} catch (ParseException ex1) {
ex = ex1;