Skip to content

Commit 929a43d

Browse files
committed
SLING-3629 - Provide an XML formatter for content.xml files
Enable a custom 'Format .content.xml file' action for the Package Explorer. I did not find a hook for overriding the WST XML 'Format Document' action so for now the formatting is not available in the editor.
1 parent ef791b0 commit 929a43d

File tree

4 files changed

+171
-2
lines changed

4 files changed

+171
-2
lines changed

eclipse/eclipse-ui/META-INF/MANIFEST.MF

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Import-Package: javax.jcr,
1717
org.apache.commons.httpclient.params;version="3.1.0",
1818
org.apache.commons.io;version="2.0.1",
1919
org.apache.jackrabbit.util,
20+
org.apache.jackrabbit.vault.fs.io;version="2.4.0",
21+
org.apache.jackrabbit.vault.util.xml.serialize;version="2.4.0",
2022
org.apache.sling.ide.artifacts,
2123
org.apache.sling.ide.eclipse.core,
2224
org.apache.sling.ide.filter,

eclipse/eclipse-ui/plugin.xml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
name="Export content to server"
185185
categoryId="org.eclipse.ui.category.window"
186186
defaultHandler="org.apache.sling.ide.eclipse.ui.internal.ExportContentAction">
187-
</command>
187+
</command>
188188
</extension>
189189

190190
<extension
@@ -420,7 +420,18 @@
420420
label="Sling Console">
421421
</consoleFactory>
422422
</extension>
423-
423+
424+
<extension
425+
point="org.eclipse.core.expressions.propertyTesters">
426+
<propertyTester
427+
id="org.apache.sling.ide.eclipse.ui.internal.ContentXmlResourceTester"
428+
type="org.apache.sling.ide.eclipse.ui.nav.model.JcrNode"
429+
namespace="org.apache.sling.ide.eclipse"
430+
properties="isContentXmlFile"
431+
class="org.apache.sling.ide.eclipse.ui.internal.ContentXmlResourceTester">
432+
</propertyTester>
433+
</extension>
434+
424435
<extension
425436
point="org.eclipse.core.expressions.definitions">
426437
<definition
@@ -429,6 +440,12 @@
429440
<adapt type="org.apache.sling.ide.eclipse.ui.nav.model.JcrNode"/>
430441
</iterate>
431442
</definition>
443+
<definition
444+
id="org.apache.sling.ide.eclipse.contentXmlFile">
445+
<iterate ifEmpty="false">
446+
<test property="org.apache.sling.ide.eclipse.isContentXmlFile"/>
447+
</iterate>
448+
</definition>
432449
<definition
433450
id="org.apache.sling.ide.eclipse.nonSlingProject">
434451
<not>
@@ -557,6 +574,15 @@
557574
<reference definitionId="org.apache.sling.ide.eclipse.jcrNode"/>
558575
</visibleWhen>
559576
</command>
577+
<command
578+
commandId="org.apache.sling.ide.eclipse.ui.actions.jcrFormatContentXml"
579+
icon="icons/obj16/sling_misc.gif"
580+
label="Format .content.xml file">
581+
<visibleWhen
582+
checkEnabled="false">
583+
<reference definitionId="org.apache.sling.ide.eclipse.contentXmlFile"/>
584+
</visibleWhen>
585+
</command>
560586
<command
561587
commandId="org.apache.sling.ide.eclipse.ui.actions.openHtmlInBrowserHandler"
562588
icon="icons/obj16/internal_browser.png"
@@ -624,6 +650,13 @@
624650
defaultHandler="org.apache.sling.ide.eclipse.ui.actions.JcrNewNodeHandler"
625651
name="Import JCR content from server...">
626652
</command>
653+
654+
<!-- Source commands -->
655+
<command
656+
id="org.apache.sling.ide.eclipse.ui.actions.jcrFormatContentXml"
657+
defaultHandler="org.apache.sling.ide.eclipse.ui.actions.JcrNodeFormatHandler"
658+
name="Format">
659+
</command>
627660
</extension>
628661

629662
<extension
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.sling.ide.eclipse.ui.actions;
18+
19+
import java.io.ByteArrayInputStream;
20+
import java.io.ByteArrayOutputStream;
21+
import java.io.IOException;
22+
23+
import org.apache.jackrabbit.vault.fs.io.DocViewFormat;
24+
import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer;
25+
import org.apache.sling.ide.eclipse.ui.internal.Activator;
26+
import org.apache.sling.ide.eclipse.ui.internal.SelectionUtils;
27+
import org.apache.sling.ide.eclipse.ui.nav.model.JcrNode;
28+
import org.eclipse.core.commands.AbstractHandler;
29+
import org.eclipse.core.commands.ExecutionEvent;
30+
import org.eclipse.core.commands.ExecutionException;
31+
import org.eclipse.core.resources.IFile;
32+
import org.eclipse.core.runtime.CoreException;
33+
import org.eclipse.core.runtime.IPath;
34+
import org.eclipse.core.runtime.IProgressMonitor;
35+
import org.eclipse.core.runtime.IStatus;
36+
import org.eclipse.core.runtime.Status;
37+
import org.eclipse.core.runtime.jobs.Job;
38+
import org.eclipse.jface.viewers.ISelection;
39+
import org.eclipse.osgi.util.NLS;
40+
import org.eclipse.ui.handlers.HandlerUtil;
41+
import org.xml.sax.InputSource;
42+
import org.xml.sax.SAXException;
43+
import org.xml.sax.XMLReader;
44+
import org.xml.sax.helpers.XMLReaderFactory;
45+
46+
public class JcrNodeFormatHandler extends AbstractHandler {
47+
48+
@Override
49+
public Object execute(ExecutionEvent event) throws ExecutionException {
50+
run(HandlerUtil.getCurrentSelection(event));
51+
return null;
52+
}
53+
54+
private void run(ISelection currentSelection) {
55+
JcrNode node = SelectionUtils.getFirst(currentSelection, JcrNode.class);
56+
if (node == null)
57+
return;
58+
59+
IFile resource = node.getFileForEditor();
60+
if ( resource == null )
61+
return;
62+
63+
IPath resourcePath = resource.getFullPath();
64+
Job job = new Job(NLS.bind("Formatting {0}", resourcePath)) {
65+
66+
@Override
67+
protected IStatus run(IProgressMonitor monitor) {
68+
try {
69+
ByteArrayOutputStream out = new ByteArrayOutputStream();
70+
XMLSerializer serializer = new XMLSerializer(out, new DocViewFormat().getXmlOutputFormat());
71+
XMLReader reader = XMLReaderFactory.createXMLReader();
72+
reader.setContentHandler(serializer);
73+
reader.setDTDHandler(serializer);
74+
reader.parse(new InputSource(resource.getContents()));
75+
76+
resource.setContents(new ByteArrayInputStream(out.toByteArray()), false, true, monitor);
77+
} catch (SAXException | IOException | CoreException e) {
78+
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, NLS.bind("Failed formatting {0}", resourcePath), e);
79+
}
80+
81+
return Status.OK_STATUS;
82+
83+
}
84+
};
85+
job.setPriority(Job.SHORT);
86+
job.setRule(resource);
87+
job.schedule();
88+
89+
}
90+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.sling.ide.eclipse.ui.internal;
18+
19+
import org.apache.sling.ide.eclipse.ui.nav.model.JcrNode;
20+
import org.eclipse.core.expressions.PropertyTester;
21+
22+
public class ContentXmlResourceTester extends PropertyTester {
23+
24+
// this class should be in the core project, but since the JcrNode class is in the ui project
25+
// we keep it here
26+
private static final String PN_IS_CONTENT_XML = "isContentXmlFile";
27+
28+
@Override
29+
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
30+
31+
if (!PN_IS_CONTENT_XML.equals(property)) {
32+
return false;
33+
}
34+
35+
if (!(receiver instanceof JcrNode)) {
36+
return false;
37+
}
38+
39+
JcrNode node = (JcrNode) receiver;
40+
41+
return node.getFileForEditor() != null;
42+
}
43+
44+
}

0 commit comments

Comments
 (0)