001: /*****************************************************************************
002: * Java Plug-in Framework (JPF)
003: * Copyright (C) 2004-2007 Dmitry Olshansky
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *****************************************************************************/package org.java.plugin.registry.xml;
019:
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.HashSet;
025: import java.util.LinkedList;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.Set;
029:
030: import org.java.plugin.registry.Extension;
031: import org.java.plugin.registry.ExtensionMultiplicity;
032: import org.java.plugin.registry.ExtensionPoint;
033: import org.java.plugin.registry.Identity;
034: import org.java.plugin.registry.IntegrityCheckReport;
035: import org.java.plugin.registry.ManifestProcessingException;
036: import org.java.plugin.registry.ParameterMultiplicity;
037: import org.java.plugin.registry.ParameterType;
038: import org.java.plugin.registry.PluginDescriptor;
039: import org.java.plugin.registry.PluginRegistry;
040: import org.java.plugin.registry.IntegrityCheckReport.ReportItem;
041:
042: /**
043: * @version $Id$
044: */
045: class ExtensionPointImpl extends PluginElementImpl<ExtensionPoint>
046: implements ExtensionPoint {
047: private final ModelExtensionPoint model;
048: private Map<String, Extension> connectedExtensions;
049: private Map<String, Extension> availableExtensions;
050: private List<ParameterDefinition> parameterDefinitions;
051: private Boolean isValid;
052: private boolean paramDefsMerged = false;
053: private List<ExtensionPoint> descendants;
054:
055: ExtensionPointImpl(final PluginDescriptorImpl descr,
056: final PluginFragmentImpl aFragment,
057: final ModelExtensionPoint aModel)
058: throws ManifestProcessingException {
059: super (descr, aFragment, aModel.getId(), aModel
060: .getDocumentation());
061: model = aModel;
062: if ((model.getParentPointId() != null)
063: && (model.getParentPluginId() == null)) {
064: log
065: .warn("parent plug-in ID not specified together with parent" //$NON-NLS-1$
066: + " extension point ID, using declaring plug-in ID," //$NON-NLS-1$
067: + " extension point is " + getUniqueId()); //$NON-NLS-1$
068: model.setParentPluginId(descr.getId());
069: }
070: parameterDefinitions = new ArrayList<ParameterDefinition>(model
071: .getParamDefs().size());
072: Set<String> names = new HashSet<String>();
073: ParameterDefinitionImpl def;
074: for (ModelParameterDef modelParameterDef : model.getParamDefs()) {
075: def = new ParameterDefinitionImpl(null, modelParameterDef);
076: if (names.contains(def.getId())) {
077: throw new ManifestProcessingException(
078: PluginRegistryImpl.PACKAGE_NAME,
079: "duplicateParameterDefinition", //$NON-NLS-1$
080: new Object[] { def.getId(), getId(),
081: descr.getId() });
082: }
083: names.add(def.getId());
084: parameterDefinitions.add(def);
085: }
086: parameterDefinitions = Collections
087: .unmodifiableList(parameterDefinitions);
088: if (log.isDebugEnabled()) {
089: log.debug("object instantiated: " + this ); //$NON-NLS-1$
090: }
091: }
092:
093: /**
094: * @see org.java.plugin.registry.UniqueIdentity#getUniqueId()
095: */
096: public String getUniqueId() {
097: return getDeclaringPluginDescriptor().getRegistry()
098: .makeUniqueId(getDeclaringPluginDescriptor().getId(),
099: getId());
100: }
101:
102: /**
103: * @see org.java.plugin.registry.ExtensionPoint#getMultiplicity()
104: */
105: public ExtensionMultiplicity getMultiplicity() {
106: return model.getExtensionMultiplicity();
107: }
108:
109: private void updateExtensionsLists() {
110: connectedExtensions = new HashMap<String, Extension>();
111: availableExtensions = new HashMap<String, Extension>();
112: for (PluginDescriptor descr : getDeclaringPluginDescriptor()
113: .getRegistry().getPluginDescriptors()) {
114: for (Extension ext : descr.getExtensions()) {
115: if (getDeclaringPluginDescriptor().getId().equals(
116: ext.getExtendedPluginId())
117: && getId().equals(ext.getExtendedPointId())) {
118: availableExtensions.put(ext.getUniqueId(), ext);
119: if (ext.isValid()) {
120: if (log.isDebugEnabled()) {
121: log.debug("extension " + ext //$NON-NLS-1$
122: + " connected to point " + this ); //$NON-NLS-1$
123: }
124: connectedExtensions.put(ext.getUniqueId(), ext);
125: } else {
126: log
127: .warn("extension " + ext.getUniqueId() //$NON-NLS-1$
128: + " is invalid and doesn't connected to" //$NON-NLS-1$
129: + " extension point " + getUniqueId()); //$NON-NLS-1$
130: }
131: }
132: }
133: }
134: }
135:
136: /**
137: * @see org.java.plugin.registry.ExtensionPoint#getAvailableExtensions()
138: */
139: public Collection<Extension> getAvailableExtensions() {
140: if (availableExtensions == null) {
141: updateExtensionsLists();
142: }
143: return Collections.unmodifiableCollection(availableExtensions
144: .values());
145: }
146:
147: /**
148: * @see org.java.plugin.registry.ExtensionPoint#getAvailableExtension(
149: * java.lang.String)
150: */
151: public Extension getAvailableExtension(final String uniqueId) {
152: if (availableExtensions == null) {
153: updateExtensionsLists();
154: }
155: Extension result = availableExtensions.get(uniqueId);
156: if (result == null) {
157: throw new IllegalArgumentException("extension " + uniqueId //$NON-NLS-1$
158: + " not available in point " + getUniqueId()); //$NON-NLS-1$
159: }
160: return result;
161: }
162:
163: /**
164: * @see org.java.plugin.registry.ExtensionPoint#isExtensionAvailable(
165: * java.lang.String)
166: */
167: public boolean isExtensionAvailable(final String uniqueId) {
168: if (availableExtensions == null) {
169: updateExtensionsLists();
170: }
171: return availableExtensions.containsKey(uniqueId);
172: }
173:
174: /**
175: * @see org.java.plugin.registry.ExtensionPoint#getConnectedExtensions()
176: */
177: public Collection<Extension> getConnectedExtensions() {
178: if (connectedExtensions == null) {
179: updateExtensionsLists();
180: }
181: return Collections.unmodifiableCollection(connectedExtensions
182: .values());
183: }
184:
185: /**
186: * @see org.java.plugin.registry.ExtensionPoint#getConnectedExtension(
187: * java.lang.String)
188: */
189: public Extension getConnectedExtension(final String uniqueId) {
190: if (connectedExtensions == null) {
191: updateExtensionsLists();
192: }
193: Extension result = connectedExtensions.get(uniqueId);
194: if (result == null) {
195: throw new IllegalArgumentException("extension " + uniqueId //$NON-NLS-1$
196: + " not connected to point " + getUniqueId()); //$NON-NLS-1$
197: }
198: return result;
199: }
200:
201: /**
202: * @see org.java.plugin.registry.ExtensionPoint#isExtensionConnected(
203: * java.lang.String)
204: */
205: public boolean isExtensionConnected(final String uniqueId) {
206: if (connectedExtensions == null) {
207: updateExtensionsLists();
208: }
209: return connectedExtensions.containsKey(uniqueId);
210: }
211:
212: /**
213: * @see org.java.plugin.registry.ExtensionPoint#isValid()
214: */
215: public boolean isValid() {
216: if (isValid == null) {
217: validate();
218: }
219: return isValid.booleanValue();
220: }
221:
222: Collection<ReportItem> validate() {
223: if ((model.getParentPluginId() != null)
224: && (model.getParentPointId() != null)) {
225: try {
226: if (!isExtensionPointAvailable(model
227: .getParentPluginId(), model.getParentPointId())) {
228: isValid = Boolean.FALSE;
229: return Collections
230: .singletonList((ReportItem) new IntegrityChecker.ReportItemImpl(
231: IntegrityCheckReport.Severity.ERROR,
232: this ,
233: IntegrityCheckReport.Error.INVALID_EXTENSION_POINT,
234: "parentExtPointNotAvailable", //$NON-NLS-1$
235: new Object[] {
236: getDeclaringPluginDescriptor()
237: .getRegistry()
238: .makeUniqueId(
239: model
240: .getParentPluginId(),
241: model
242: .getParentPointId()),
243: getUniqueId() }));
244: }
245: } catch (Throwable t) {
246: isValid = Boolean.FALSE;
247: if (log.isDebugEnabled()) {
248: log
249: .debug(
250: "failed checking availability of extension point " //$NON-NLS-1$
251: + getDeclaringPluginDescriptor()
252: .getRegistry()
253: .makeUniqueId(
254: model
255: .getParentPluginId(),
256: model
257: .getParentPointId()),
258: t);
259: }
260: return Collections
261: .singletonList((ReportItem) new IntegrityChecker.ReportItemImpl(
262: IntegrityCheckReport.Severity.ERROR,
263: this ,
264: IntegrityCheckReport.Error.INVALID_EXTENSION_POINT,
265: "parentExtPointAvailabilityCheckFailed", //$NON-NLS-1$
266: new Object[] {
267: getDeclaringPluginDescriptor()
268: .getRegistry()
269: .makeUniqueId(
270: model
271: .getParentPluginId(),
272: model
273: .getParentPointId()),
274: getUniqueId(), t }));
275: }
276: }
277: switch (getMultiplicity()) {
278: case ANY:
279: isValid = Boolean.TRUE;
280: return Collections.emptyList();
281: case ONE:
282: isValid = Boolean
283: .valueOf(getAvailableExtensions().size() == 1);
284: if (!isValid.booleanValue()) {
285: return Collections
286: .singletonList((ReportItem) new IntegrityChecker.ReportItemImpl(
287: IntegrityCheckReport.Severity.ERROR,
288: this ,
289: IntegrityCheckReport.Error.INVALID_EXTENSION_POINT,
290: "toManyOrFewExtsConnected", getUniqueId())); //$NON-NLS-1$
291: }
292: break;
293: case NONE:
294: isValid = Boolean
295: .valueOf(getAvailableExtensions().size() == 0);
296: if (!isValid.booleanValue()) {
297: return Collections
298: .singletonList((ReportItem) new IntegrityChecker.ReportItemImpl(
299: IntegrityCheckReport.Severity.ERROR,
300: this ,
301: IntegrityCheckReport.Error.INVALID_EXTENSION_POINT,
302: "extsConnectedToAbstractExtPoint", getUniqueId())); //$NON-NLS-1$
303: }
304: break;
305: case ONE_PER_PLUGIN:
306: isValid = Boolean.TRUE;
307: final Set<String> foundPlugins = new HashSet<String>();
308: String pluginId;
309: for (Extension extension : getAvailableExtensions()) {
310: pluginId = extension.getDeclaringPluginDescriptor()
311: .getId();
312: if (!foundPlugins.add(pluginId)) {
313: isValid = Boolean.FALSE;
314: return Collections
315: .singletonList((ReportItem) new IntegrityChecker.ReportItemImpl(
316: IntegrityCheckReport.Severity.ERROR,
317: this ,
318: IntegrityCheckReport.Error.INVALID_EXTENSION_POINT,
319: "toManyExtsConnected", getUniqueId())); //$NON-NLS-1$
320: }
321: }
322: break;
323: }
324: return Collections.emptyList();
325: }
326:
327: private boolean isExtensionPointAvailable(final String pluginId,
328: final String pointId) {
329: PluginRegistry registry = getDeclaringPluginDescriptor()
330: .getRegistry();
331: if (!registry.isPluginDescriptorAvailable(pluginId)) {
332: return false;
333: }
334: for (ExtensionPoint extensionPoint : registry
335: .getPluginDescriptor(pluginId).getExtensionPoints()) {
336: if (extensionPoint.getId().equals(pointId)) {
337: return true;
338: }
339: }
340: return false;
341: }
342:
343: /**
344: * @see org.java.plugin.registry.ExtensionPoint#getParameterDefinitions()
345: */
346: public Collection<ParameterDefinition> getParameterDefinitions() {
347: if ((model.getParentPluginId() == null)
348: || (model.getParentPointId() == null)
349: || paramDefsMerged) {
350: return parameterDefinitions;
351: }
352: final Set<String> names = new HashSet<String>();
353: final Collection<ParameterDefinition> parentParamDefs = getDeclaringPluginDescriptor()
354: .getRegistry().getExtensionPoint(
355: model.getParentPluginId(),
356: model.getParentPointId())
357: .getParameterDefinitions();
358: final List<ParameterDefinition> newParamDefs = new ArrayList<ParameterDefinition>(
359: parameterDefinitions.size() + parentParamDefs.size());
360: for (ParameterDefinition def : parameterDefinitions) {
361: names.add(def.getId());
362: newParamDefs.add(def);
363: }
364: for (ParameterDefinition def : parentParamDefs) {
365: if (names.contains(def.getId()))
366: continue;
367: newParamDefs.add(def);
368: }
369: paramDefsMerged = true;
370: parameterDefinitions = Collections
371: .unmodifiableList(newParamDefs);
372: return parameterDefinitions;
373: }
374:
375: /**
376: * @see org.java.plugin.registry.ExtensionPoint#getParameterDefinition(
377: * java.lang.String)
378: */
379: public ParameterDefinition getParameterDefinition(final String id) {
380: for (ParameterDefinition parameterDefinition : getParameterDefinitions()) {
381: ParameterDefinitionImpl def = (ParameterDefinitionImpl) parameterDefinition;
382: if (def.getId().equals(id)) {
383: return def;
384: }
385: }
386: throw new IllegalArgumentException(
387: "parameter definition with ID " + id //$NON-NLS-1$
388: + " not found in extension point " + getUniqueId() //$NON-NLS-1$
389: + " and all it parents"); //$NON-NLS-1$
390: }
391:
392: /**
393: * @see org.java.plugin.registry.ExtensionPoint#getParentPluginId()
394: */
395: public String getParentPluginId() {
396: return model.getParentPluginId();
397: }
398:
399: /**
400: * @see org.java.plugin.registry.ExtensionPoint#getParentExtensionPointId()
401: */
402: public String getParentExtensionPointId() {
403: return model.getParentPointId();
404: }
405:
406: /**
407: * @see org.java.plugin.registry.ExtensionPoint#isSuccessorOf(
408: * org.java.plugin.registry.ExtensionPoint)
409: */
410: public boolean isSuccessorOf(final ExtensionPoint extensionPoint) {
411: if ((model.getParentPluginId() == null)
412: || (model.getParentPointId() == null)) {
413: return false;
414: }
415: if (model.getParentPluginId().equals(
416: extensionPoint.getDeclaringPluginDescriptor().getId())
417: && model.getParentPointId().equals(
418: extensionPoint.getId())) {
419: return true;
420: }
421: try {
422: return getDeclaringPluginDescriptor().getRegistry()
423: .getExtensionPoint(model.getParentPluginId(),
424: model.getParentPointId()).isSuccessorOf(
425: extensionPoint);
426: } catch (IllegalArgumentException iae) {
427: return false;
428: }
429: }
430:
431: private void collectDescendants() {
432: descendants = new LinkedList<ExtensionPoint>();
433: for (PluginDescriptor descr : getDeclaringPluginDescriptor()
434: .getRegistry().getPluginDescriptors()) {
435: for (ExtensionPoint extp : descr.getExtensionPoints()) {
436: if (extp.isSuccessorOf(this )) {
437: if (log.isDebugEnabled()) {
438: log.debug("extension point " + extp //$NON-NLS-1$
439: + " is descendant of point " + this ); //$NON-NLS-1$
440: }
441: descendants.add(extp);
442: }
443: }
444: }
445: descendants = Collections.unmodifiableList(descendants);
446: }
447:
448: /**
449: * @see org.java.plugin.registry.ExtensionPoint#getDescendants()
450: */
451: public Collection<ExtensionPoint> getDescendants() {
452: if (descendants == null) {
453: collectDescendants();
454: }
455: return descendants;
456: }
457:
458: /**
459: * @see java.lang.Object#toString()
460: */
461: @Override
462: public String toString() {
463: return "{ExtensionPoint: uid=" + getUniqueId() + "}"; //$NON-NLS-1$ //$NON-NLS-2$
464: }
465:
466: void registryChanged() {
467: isValid = null;
468: connectedExtensions = null;
469: availableExtensions = null;
470: descendants = null;
471: }
472:
473: class ParameterDefinitionImpl extends
474: PluginElementImpl<ParameterDefinition> implements
475: ParameterDefinition {
476: private List<ParameterDefinition> subDefinitions;
477: private final ParameterDefinitionImpl super Definition;
478: private final ModelParameterDef modelParamDef;
479: private final ParameterValueParser valueParser;
480:
481: ParameterDefinitionImpl(
482: final ParameterDefinitionImpl aSuperDefinition,
483: final ModelParameterDef aModel)
484: throws ManifestProcessingException {
485: super (ExtensionPointImpl.this
486: .getDeclaringPluginDescriptor(),
487: ExtensionPointImpl.this
488: .getDeclaringPluginFragment(), aModel
489: .getId(), aModel.getDocumentation());
490: super Definition = aSuperDefinition;
491: modelParamDef = aModel;
492: valueParser = new ParameterValueParser(
493: getDeclaringPluginDescriptor().getRegistry(), this ,
494: modelParamDef.getDefaultValue());
495: if (!valueParser.isParsingSucceeds()) {
496: log
497: .warn("parsing default value for parameter definition " //$NON-NLS-1$
498: + this + " failed, message is: " //$NON-NLS-1$
499: + valueParser.getParsingMessage());
500: throw new ManifestProcessingException(
501: PluginRegistryImpl.PACKAGE_NAME,
502: "invalidDefaultValueAttribute", //$NON-NLS-1$
503: new Object[] {
504: modelParamDef.getDefaultValue(),
505: ExtensionPointImpl.this .getId(),
506: ExtensionPointImpl.this
507: .getDeclaringPluginDescriptor()
508: .getId() });
509: }
510: if (ParameterType.ANY == modelParamDef.getType()) {
511: subDefinitions = Collections.emptyList();
512: } else {
513: subDefinitions = new ArrayList<ParameterDefinition>(
514: modelParamDef.getParamDefs().size());
515: final Set<String> names = new HashSet<String>();
516: for (ModelParameterDef modelParameterDef : modelParamDef
517: .getParamDefs()) {
518: ParameterDefinitionImpl def = new ParameterDefinitionImpl(
519: this , modelParameterDef);
520: if (names.contains(def.getId())) {
521: throw new ManifestProcessingException(
522: PluginRegistryImpl.PACKAGE_NAME,
523: "duplicateParameterDefinition", //$NON-NLS-1$
524: new Object[] {
525: def.getId(),
526: ExtensionPointImpl.this .getId(),
527: ExtensionPointImpl.this
528: .getDeclaringPluginDescriptor()
529: .getId() });
530: }
531: names.add(def.getId());
532: subDefinitions.add(def);
533: }
534: subDefinitions = Collections
535: .unmodifiableList(subDefinitions);
536: }
537: if (log.isDebugEnabled()) {
538: log.debug("object instantiated: " + this ); //$NON-NLS-1$
539: }
540: }
541:
542: ParameterValueParser getValueParser() {
543: return valueParser;
544: }
545:
546: /**
547: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
548: * #getDeclaringExtensionPoint()
549: */
550: public ExtensionPoint getDeclaringExtensionPoint() {
551: return ExtensionPointImpl.this ;
552: }
553:
554: /**
555: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
556: * #getMultiplicity()
557: */
558: public ParameterMultiplicity getMultiplicity() {
559: return modelParamDef.getMultiplicity();
560: }
561:
562: /**
563: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
564: * #getSubDefinitions()
565: */
566: public Collection<ParameterDefinition> getSubDefinitions() {
567: return subDefinitions;
568: }
569:
570: /**
571: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
572: * #getSuperDefinition()
573: */
574: public ParameterDefinition getSuperDefinition() {
575: return super Definition;
576: }
577:
578: /**
579: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
580: * #getSubDefinition(java.lang.String)
581: */
582: public ParameterDefinition getSubDefinition(final String id) {
583: for (ParameterDefinition parameterDefinition : subDefinitions) {
584: ParameterDefinitionImpl def = (ParameterDefinitionImpl) parameterDefinition;
585: if (def.getId().equals(id)) {
586: return def;
587: }
588: }
589: throw new IllegalArgumentException(
590: "parameter definition with ID " + id //$NON-NLS-1$
591: + " not found in extension point " + getUniqueId()); //$NON-NLS-1$
592: }
593:
594: /**
595: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition#getType()
596: */
597: public ParameterType getType() {
598: return modelParamDef.getType();
599: }
600:
601: /**
602: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
603: * #getCustomData()
604: */
605: public String getCustomData() {
606: return modelParamDef.getCustomData();
607: }
608:
609: /**
610: * @see org.java.plugin.registry.ExtensionPoint.ParameterDefinition
611: * #getDefaultValue()
612: */
613: public String getDefaultValue() {
614: return modelParamDef.getDefaultValue();
615: }
616:
617: /**
618: * @see java.lang.Object#toString()
619: */
620: @Override
621: public String toString() {
622: return "{PluginExtensionPoint.ParameterDefinition: extPointUid=" //$NON-NLS-1$
623: + getDeclaringExtensionPoint().getUniqueId()
624: + "; id=" + getId() //$NON-NLS-1$
625: + "}"; //$NON-NLS-1$
626: }
627:
628: /**
629: * @see org.java.plugin.registry.xml.IdentityImpl#isEqualTo(
630: * org.java.plugin.registry.Identity)
631: */
632: @Override
633: protected boolean isEqualTo(final Identity idt) {
634: if (!super .isEqualTo(idt)) {
635: return false;
636: }
637: ParameterDefinitionImpl other = (ParameterDefinitionImpl) idt;
638: if ((getSuperDefinition() == null)
639: && (other.getSuperDefinition() == null)) {
640: return true;
641: }
642: if ((getSuperDefinition() == null)
643: || (other.getSuperDefinition() == null)) {
644: return false;
645: }
646: return getSuperDefinition().equals(
647: other.getSuperDefinition());
648: }
649: }
650: }
|