001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.xml.catalog.impl.sun;
043:
044: import java.awt.Image;
045: import java.io.*;
046: import java.beans.*;
047: import java.util.*;
048: import java.net.*;
049:
050: import org.xml.sax.*;
051:
052: import org.netbeans.modules.xml.catalog.spi.*;
053:
054: import org.apache.xml.resolver.tools.CatalogResolver;
055: import org.apache.xml.resolver.CatalogManager;
056: import org.openide.util.NbBundle;
057:
058: /**
059: * SPI implementation that bridges to Sun's Resolvers 1.1.
060: * <p>
061: * It uses heavily lazy initialization to eliminate differences between an
062: * instance constructed by the contructor <b>or</b> by deserialization process.
063: * The approach also speeds up setup time.
064: *
065: * @author Petr Kuzel
066: */
067: public final class Catalog implements
068: org.netbeans.modules.xml.catalog.spi.CatalogReader,
069: CatalogDescriptor, Serializable, EntityResolver {
070:
071: private static final long serialVersionUID = 123659121L;
072:
073: private transient PropertyChangeSupport pchs;
074:
075: private transient EntityResolver peer;
076:
077: private transient String desc;
078:
079: // a catalog source location
080: private String location;
081:
082: // a public preference
083: private boolean preference = true;
084:
085: private static final String PROP_LOCATION = "cat-loc";
086:
087: private static final String PROP_PREF_PUBLIC = "cat-pref";
088:
089: private static final String PROP_DESC = CatalogDescriptor.PROP_CATALOG_DESC;
090:
091: /** Creates a new instance of Catalog */
092: public Catalog() {
093: }
094:
095: /**
096: * Deserialization 'constructor'.
097: */
098: public void readObject(ObjectInputStream in) throws IOException,
099: ClassNotFoundException {
100: in.defaultReadObject();
101:
102: // lazy init transient fields, see getPCHS() and getPeer() methods
103: setShortDescription(NbBundle.getMessage(Catalog.class,
104: "MSG_prepared", location));
105: }
106:
107: /**
108: * Set Catalog source (a URL).
109: */
110: public synchronized void setLocation(String location) {
111: String old = this .location;
112: this .location = location;
113: peer = null; // lazy init
114: getPCHS().firePropertyChange(PROP_LOCATION, old, location);
115: updateDisplayName();
116: }
117:
118: /**
119: * Access the location value.
120: */
121: public String getLocation() {
122: return location;
123: }
124:
125: /**
126: * Set public resolving preference.
127: */
128: public void setPreferPublic(boolean val) {
129: boolean old = preference;
130: this .preference = val;
131: getPCHS().firePropertyChange(PROP_LOCATION, old, val);
132: }
133:
134: /**
135: * Access the public ID preference flag.
136: */
137: public boolean isPreferPublic() {
138: return preference;
139: }
140:
141: /**
142: * Optional operation allowing to listen at catalog for changes.
143: * @throws UnsupportedOpertaionException if not supported by the implementation.
144: */
145: public void addCatalogListener(CatalogListener l) {
146: throw new UnsupportedOperationException();
147: }
148:
149: /** Registers new listener. */
150: public void addPropertyChangeListener(PropertyChangeListener l) {
151: getPCHS().addPropertyChangeListener(l);
152: }
153:
154: /**
155: * @return I18N display name
156: */
157: public String getDisplayName() {
158: String src = location;
159: if (src == null || "".equals(src.trim())) {
160: return NbBundle.getMessage(Catalog.class,
161: "PROP_missing_location");
162: } else {
163: return NbBundle.getMessage(Catalog.class, "TITLE_catalog",
164: location);
165: }
166: }
167:
168: public String getName() {
169: return getClass() + location + preference;
170: }
171:
172: /**
173: * Notify listeners that display name have changed.
174: */
175: public void updateDisplayName() {
176: String name = getDisplayName();
177: getPCHS().firePropertyChange(
178: CatalogDescriptor.PROP_CATALOG_NAME, null, name);
179: }
180:
181: /**
182: * Return visuaized state of given catalog.
183: * @param type of icon defined by JavaBeans specs
184: * @return icon representing current state or null
185: */
186: public Image getIcon(int type) {
187: return null;
188: }
189:
190: /**
191: * Get String iterator representing all public IDs registered in catalog.
192: * @return null if cannot proceed, try later.
193: */
194: public Iterator getPublicIDs() {
195: Object p = getPeer();
196: if (p instanceof org.apache.xml.resolver.tools.CatalogResolver) {
197: org.apache.xml.resolver.Catalog cat = ((org.apache.xml.resolver.tools.CatalogResolver) p)
198: .getCatalog();
199: return cat.getPublicIDs();
200: }
201: return null;
202: }
203:
204: /**
205: * @return I18N short description
206: */
207: public String getShortDescription() {
208: return desc;
209: }
210:
211: public void setShortDescription(String desc) {
212: String old = this .desc;
213: this .desc = desc;
214: getPCHS().firePropertyChange(PROP_DESC, old, desc);
215: }
216:
217: /**
218: * Get registered systemid for given public Id or null if not registered.
219: * @return null if not registered
220: */
221: public String getSystemID(String publicId) {
222: Object p = getPeer();
223: if (p instanceof org.apache.xml.resolver.tools.CatalogResolver)
224: try {
225: return ((org.apache.xml.resolver.tools.CatalogResolver) p)
226: .getCatalog().resolveSystem(publicId);
227: } catch (java.net.MalformedURLException ex) {
228: } catch (java.io.IOException ex) {
229: }
230: return null;
231: }
232:
233: /**
234: * Refresh content according to content of mounted catalog.
235: */
236: public synchronized void refresh() {
237: peer = createPeer(location, preference);
238: }
239:
240: /**
241: * Optional operation couled with addCatalogListener.
242: * @throws UnsupportedOpertaionException if not supported by the implementation.
243: */
244: public void removeCatalogListener(CatalogListener l) {
245: throw new UnsupportedOperationException();
246: }
247:
248: /** Unregister the listener. */
249: public void removePropertyChangeListener(PropertyChangeListener l) {
250: getPCHS().removePropertyChangeListener(l);
251: }
252:
253: /**
254: * Delegate entity resution process to peer if exists.
255: */
256: public InputSource resolveEntity(String publicID, String systemID)
257: throws SAXException, IOException {
258: return getPeer().resolveEntity(publicID, systemID);
259: }
260:
261: /** We are a key and must retain equals immutability
262: public boolean equals(Object obj) {
263: if (obj instanceof Catalog) {
264: Catalog cat = (Catalog) obj;
265: if (this.location == null && cat.location != null) return false;
266: if ((this.location != null && this.location.equals(cat.location)) == false) return false;
267: return (this.preference == cat.preference);
268: }
269: return false;
270: }
271:
272:
273: public int hashCode() {
274: return (location != null ? location.hashCode() : 0) ^ (preference?13:7);
275: }
276: */
277: /**
278: * Factory new peer and load data into it.
279: * As a side effect set short description.
280: * @return EntityResolver never <code>null</code>
281: */
282: private EntityResolver createPeer(String location, boolean pref) {
283: try {
284: CatalogManager manager = new CatalogManager(null);
285: manager.setUseStaticCatalog(false);
286: manager.setPreferPublic(pref);
287:
288: CatalogResolver catalogResolver = new CatalogResolver(
289: manager);
290: org.apache.xml.resolver.Catalog cat = catalogResolver
291: .getCatalog();
292: cat.parseCatalog(new URL(location));
293: setShortDescription(NbBundle.getMessage(Catalog.class,
294: "DESC_loaded"));
295: return catalogResolver;
296: } catch (IOException ex) {
297: setShortDescription(NbBundle.getMessage(Catalog.class,
298: "DESC_error_loading", ex.getLocalizedMessage()));
299: //if ( Util.THIS.isLoggable() ) /* then */ Util.THIS.debug("I/O error loading catalog " + location, ex);
300: }
301:
302: // return dumb peer
303: return new EntityResolver() {
304: public InputSource resolveEntity(String p, String s) {
305: return null;
306: }
307: };
308: }
309:
310: /**
311: * Lazy init PropertyChangeSupport and return it.
312: */
313: private synchronized PropertyChangeSupport getPCHS() {
314: if (pchs == null)
315: pchs = new PropertyChangeSupport(this );
316: return pchs;
317: }
318:
319: /**
320: * Lazy init peer and return it.
321: */
322: private synchronized EntityResolver getPeer() {
323:
324: if (peer == null)
325: peer = createPeer(location, preference);
326: return peer;
327: }
328:
329: /**
330: * Get registered URI for the given name or null if not registered.
331: * @return null if not registered
332: */
333: public String resolveURI(String name) {
334: Object p = getPeer();
335: if (p instanceof org.apache.xml.resolver.tools.CatalogResolver)
336: try {
337: return ((org.apache.xml.resolver.tools.CatalogResolver) p)
338: .getCatalog().resolveURI(name);
339: } catch (java.net.MalformedURLException ex) {
340: } catch (java.io.IOException ex) {
341: }
342: return null;
343: }
344:
345: /**
346: * Get registered URI for the given publicId or null if not registered.
347: * @return null if not registered
348: */
349: public String resolvePublic(String publicId) {
350: Object p = getPeer();
351: if (p instanceof org.apache.xml.resolver.tools.CatalogResolver)
352: try {
353: return ((org.apache.xml.resolver.tools.CatalogResolver) p)
354: .getCatalog().resolvePublic(publicId, null);
355: } catch (java.net.MalformedURLException ex) {
356: } catch (java.io.IOException ex) {
357: }
358: return null;
359: }
360:
361: }
|