001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.config;
017:
018: import javax.enterprise.deploy.model.DeployableObject;
019: import javax.enterprise.deploy.shared.ActionType;
020: import javax.enterprise.deploy.shared.CommandType;
021: import javax.enterprise.deploy.shared.DConfigBeanVersionType;
022: import javax.enterprise.deploy.shared.ModuleType;
023: import javax.enterprise.deploy.shared.StateType;
024: import javax.enterprise.deploy.spi.DeploymentConfiguration;
025: import javax.enterprise.deploy.spi.DeploymentManager;
026: import javax.enterprise.deploy.spi.Target;
027: import javax.enterprise.deploy.spi.TargetModuleID;
028: import javax.enterprise.deploy.spi.exceptions.DConfigBeanVersionUnsupportedException;
029: import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
030: import javax.enterprise.deploy.spi.exceptions.InvalidModuleException;
031: import javax.enterprise.deploy.spi.exceptions.OperationUnsupportedException;
032: import javax.enterprise.deploy.spi.exceptions.TargetException;
033: import javax.enterprise.deploy.spi.status.ClientConfiguration;
034: import javax.enterprise.deploy.spi.status.DeploymentStatus;
035: import javax.enterprise.deploy.spi.status.ProgressEvent;
036: import javax.enterprise.deploy.spi.status.ProgressListener;
037: import javax.enterprise.deploy.spi.status.ProgressObject;
038: import java.io.File;
039: import java.io.InputStream;
040: import java.io.PrintWriter;
041: import java.io.Serializable;
042: import java.io.StringWriter;
043: import java.lang.reflect.Field;
044: import java.lang.reflect.Modifier;
045: import java.util.ArrayList;
046: import java.util.Collections;
047: import java.util.HashSet;
048: import java.util.Iterator;
049: import java.util.List;
050: import java.util.Locale;
051: import java.util.Map;
052: import java.util.Properties;
053: import java.util.Set;
054: import java.util.SortedMap;
055: import java.util.TreeMap;
056: import java.util.TreeSet;
057:
058: public class OpenEJBDeploymentManager implements DeploymentManager {
059: public static final DConfigBeanVersionType DEFAULT_DCONFIG_BEAN_VERSION = DConfigBeanVersionType.V1_4;
060: public static final String DEFAULT_TARGET_NAME = "DefaultTarget";
061:
062: private Deployment deployment;
063: private final Locale locale;
064: private final DConfigBeanVersionType dconfigBeanVersion;
065: private final Target defaultTarget;
066: private final SortedMap<String, Target> targets;
067: private final List<String> targetPaths;
068:
069: public OpenEJBDeploymentManager() {
070: locale = Locale.getDefault();
071: dconfigBeanVersion = OpenEJBDeploymentManager.DEFAULT_DCONFIG_BEAN_VERSION;
072: defaultTarget = null;
073: targets = null;
074: targetPaths = null;
075: }
076:
077: public OpenEJBDeploymentManager(Deployment deployment)
078: throws DeploymentManagerCreationException {
079: this .deployment = deployment;
080: Properties properties = deployment.getProperties();
081:
082: // locale - local used by the server
083: String localeString = properties.getProperty("locale");
084: if (localeString != null) {
085: locale = new Locale(localeString);
086: } else {
087: locale = Locale.getDefault();
088: }
089:
090: // dconfig.bean.version - dconfig bean version supported by the server
091: String dconfigBeanVersionString = properties
092: .getProperty("locale");
093: dconfigBeanVersion = OpenEJBDeploymentManager
094: .parseDConfigBeanVersionType(dconfigBeanVersionString);
095:
096: // target.* - known targets available on the server
097: // target.*.description - known targets available on the server
098: SortedMap<String, Target> targets = new TreeMap<String, Target>();
099: for (Iterator<Map.Entry<Object, Object>> iterator = properties
100: .entrySet().iterator(); iterator.hasNext();) {
101: Map.Entry entry = iterator.next();
102: String key = (String) entry.getKey();
103: String targetName = (String) entry.getValue();
104: if (key.startsWith("target.")
105: && !key.endsWith(".description")) {
106: String targetDescription = properties.getProperty(key
107: + ".description");
108: TargetImpl target = new TargetImpl(targetName,
109: targetDescription);
110: targets.put(targetName, target);
111: }
112: }
113:
114: // target.default - default target
115: String defaultTargetName = properties
116: .getProperty("target.default");
117: if (defaultTargetName == null)
118: defaultTargetName = OpenEJBDeploymentManager.DEFAULT_TARGET_NAME;
119: if (!targets.containsKey(defaultTargetName)) {
120: targets.put(defaultTargetName, new TargetImpl(
121: defaultTargetName, null));
122: }
123: defaultTarget = targets.get(defaultTargetName);
124:
125: this .targets = Collections.unmodifiableSortedMap(targets);
126:
127: targetPaths = new ArrayList<String>();
128: for (String targetName : targets.keySet()) {
129: targetPaths.add(targetName + "/");
130: }
131: Collections.reverse(targetPaths);
132: }
133:
134: public void release() {
135: if (deployment != null) {
136: deployment.release();
137: deployment = null;
138: }
139: }
140:
141: public Target[] getTargets() {
142: if (deployment == null)
143: throw new IllegalStateException(
144: "Deployment manager is disconnected");
145:
146: return targets.values().toArray(new Target[targets.size()]);
147: }
148:
149: public TargetModuleID[] getAvailableModules(ModuleType moduleType,
150: Target[] targetList) throws TargetException {
151: if (deployment == null)
152: throw new IllegalStateException(
153: "Deployment manager is disconnected");
154:
155: try {
156: String type = null;
157: if (type != null) {
158: moduleType.toString();
159: }
160: Set<String> targetModulesStrings = deployment.list(type,
161: null, toTargetSet(targetList));
162: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModulesStrings);
163: return targetModules
164: .toArray(new TargetModuleID[targetModules.size()]);
165: } catch (DeploymentException e) {
166: throw new IllegalStateException(
167: "DeployerException while listing deployments", e);
168: }
169: }
170:
171: public TargetModuleID[] getNonRunningModules(ModuleType moduleType,
172: Target[] targetList) throws TargetException {
173: if (deployment == null)
174: throw new IllegalStateException(
175: "Deployment manager is disconnected");
176:
177: try {
178: String type = null;
179: if (type != null) {
180: moduleType.toString();
181: }
182: Set<String> targetModulesStrings = deployment.list(type,
183: "stopped", toTargetSet(targetList));
184: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModulesStrings);
185: return targetModules
186: .toArray(new TargetModuleID[targetModules.size()]);
187: } catch (DeploymentException e) {
188: throw new IllegalStateException(
189: "DeployerException while listing deployments", e);
190: }
191: }
192:
193: public TargetModuleID[] getRunningModules(ModuleType moduleType,
194: Target[] targetList) throws TargetException {
195: if (deployment == null)
196: throw new IllegalStateException(
197: "Deployment manager is disconnected");
198:
199: try {
200: String type = null;
201: if (type != null) {
202: moduleType.toString();
203: }
204: Set<String> targetModulesStrings = deployment.list(type,
205: "running", toTargetSet(targetList));
206: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModulesStrings);
207: return targetModules
208: .toArray(new TargetModuleID[targetModules.size()]);
209: } catch (DeploymentException e) {
210: throw new IllegalStateException(
211: "DeployerException while listing deployments", e);
212: }
213: }
214:
215: public ProgressObject distribute(Target[] targetList,
216: File moduleArchive, File deploymentPlan) {
217: if (deployment == null)
218: throw new IllegalStateException(
219: "Deployment manager is disconnected");
220:
221: // todo merge files
222: try {
223: Set<String> targetModuleStrings = deployment.deploy(
224: toTargetSet(targetList), moduleArchive);
225: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModuleStrings);
226: return new ProgressObjectImpl(CommandType.DISTRIBUTE,
227: targetModules);
228: } catch (DeploymentException e) {
229: return new ProgressObjectImpl(CommandType.DISTRIBUTE, e);
230: }
231: }
232:
233: public ProgressObject distribute(Target[] targetList,
234: InputStream moduleArchive, InputStream deploymentPlan) {
235: if (deployment == null)
236: throw new IllegalStateException(
237: "Deployment manager is disconnected");
238:
239: // todo merge files
240: try {
241: Set<String> targetModuleStrings = deployment.deploy(
242: toTargetSet(targetList), null);
243: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModuleStrings);
244: return new ProgressObjectImpl(CommandType.DISTRIBUTE,
245: targetModules);
246: } catch (DeploymentException e) {
247: return new ProgressObjectImpl(CommandType.DISTRIBUTE, e);
248: }
249: }
250:
251: public ProgressObject start(TargetModuleID[] moduleIdList) {
252: if (deployment == null)
253: throw new IllegalStateException(
254: "Deployment manager is disconnected");
255:
256: try {
257: Set<String> targetModuleStrings = deployment
258: .start(toModuleSet(moduleIdList));
259: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModuleStrings);
260: return new ProgressObjectImpl(CommandType.START,
261: targetModules);
262: } catch (DeploymentException e) {
263: return new ProgressObjectImpl(CommandType.START, e);
264: }
265: }
266:
267: public ProgressObject stop(TargetModuleID[] moduleIdList) {
268: if (deployment == null)
269: throw new IllegalStateException(
270: "Deployment manager is disconnected");
271:
272: try {
273: Set<String> targetModuleStrings = deployment
274: .stop(toModuleSet(moduleIdList));
275: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModuleStrings);
276: return new ProgressObjectImpl(CommandType.STOP,
277: targetModules);
278: } catch (DeploymentException e) {
279: return new ProgressObjectImpl(CommandType.STOP, e);
280: }
281: }
282:
283: public ProgressObject undeploy(TargetModuleID[] moduleIdList) {
284: if (deployment == null)
285: throw new IllegalStateException(
286: "Deployment manager is disconnected");
287:
288: try {
289: Set<String> targetModuleStrings = deployment
290: .undeploy(toModuleSet(moduleIdList));
291: Set<TargetModuleID> targetModules = toTargetModuleIds(targetModuleStrings);
292: return new ProgressObjectImpl(CommandType.UNDEPLOY,
293: targetModules);
294: } catch (DeploymentException e) {
295: return new ProgressObjectImpl(CommandType.UNDEPLOY, e);
296: }
297: }
298:
299: public boolean isRedeploySupported() {
300: return false;
301: }
302:
303: public ProgressObject redeploy(TargetModuleID[] moduleIDList,
304: File moduleArchive, File deploymentPlan) {
305: throw new UnsupportedOperationException(
306: "redeploy is not supported");
307: }
308:
309: public ProgressObject redeploy(TargetModuleID[] moduleIDList,
310: InputStream moduleArchive, InputStream deploymentPlan) {
311: throw new UnsupportedOperationException(
312: "redeploy is not supported");
313: }
314:
315: public Locale[] getSupportedLocales() {
316: return new Locale[] { getDefaultLocale() };
317: }
318:
319: public Locale getCurrentLocale() {
320: return getDefaultLocale();
321: }
322:
323: public Locale getDefaultLocale() {
324: return locale;
325: }
326:
327: public boolean isLocaleSupported(Locale locale) {
328: return getDefaultLocale().equals(locale);
329: }
330:
331: public void setLocale(Locale locale) {
332: if (!isLocaleSupported(locale)) {
333: throw new UnsupportedOperationException(
334: "Unsupported locale");
335: }
336: }
337:
338: public DConfigBeanVersionType getDConfigBeanVersion() {
339: return dconfigBeanVersion;
340: }
341:
342: public boolean isDConfigBeanVersionSupported(
343: DConfigBeanVersionType version) {
344: return dconfigBeanVersion.equals(version);
345: }
346:
347: public void setDConfigBeanVersion(DConfigBeanVersionType version)
348: throws DConfigBeanVersionUnsupportedException {
349: if (!isDConfigBeanVersionSupported(version)) {
350: throw new DConfigBeanVersionUnsupportedException(
351: "Version not supported " + version);
352: }
353: }
354:
355: public DeploymentConfiguration createConfiguration(
356: DeployableObject deployableObject)
357: throws InvalidModuleException {
358: throw new InvalidModuleException("Not supported: "
359: + deployableObject.getType());
360: }
361:
362: private Target getTargetFor(String moduleId) {
363: for (String targetName : targetPaths) {
364: if (moduleId.startsWith(moduleId)) {
365: return targets.get(targetName);
366: }
367: }
368: return null;
369: }
370:
371: private Set<TargetModuleID> toTargetModuleIds(Set<String> modules) {
372: Set<TargetModuleID> targetModuleIds = new HashSet<TargetModuleID>();
373: for (String module : modules) {
374: String moduleId;
375: String webUrl;
376:
377: int spaceIndex = module.indexOf(' ');
378: if (spaceIndex > 1) {
379: moduleId = module.substring(0, spaceIndex);
380: webUrl = module.substring(spaceIndex + 1);
381: } else {
382: moduleId = module;
383: webUrl = null;
384: }
385:
386: Target target = getTargetFor(moduleId);
387: if (target != null) {
388: if (moduleId.startsWith(target.getName())) {
389: moduleId = moduleId.substring(target.getName()
390: .length());
391: }
392: } else {
393: target = defaultTarget;
394: }
395:
396: TargetModuleIDImpl targetModuleID = new TargetModuleIDImpl(
397: target, moduleId, webUrl);
398: targetModuleIds.add(targetModuleID);
399: }
400:
401: // todo link children
402:
403: return targetModuleIds;
404: }
405:
406: private Set<String> toTargetSet(Target[] targets) {
407: if (targets == null)
408: return Collections.emptySet();
409:
410: TreeSet<String> targetSet = new TreeSet<String>();
411: for (Target target : targets) {
412: targetSet.add(target.getName());
413: }
414: return targetSet;
415: }
416:
417: private Set<String> toModuleSet(TargetModuleID[] moduleIDList) {
418: if (moduleIDList == null)
419: return Collections.emptySet();
420:
421: TreeSet<String> moduleSet = new TreeSet<String>();
422: for (TargetModuleID module : moduleIDList) {
423: moduleSet.add(module.getTarget().getName() + "/"
424: + module.getModuleID());
425: }
426: return moduleSet;
427: }
428:
429: public static DConfigBeanVersionType parseDConfigBeanVersionType(
430: String string) throws DeploymentManagerCreationException {
431: if (string == null) {
432: return OpenEJBDeploymentManager.DEFAULT_DCONFIG_BEAN_VERSION;
433: }
434: try {
435: Field field = DConfigBeanVersionType.class.getField(string);
436: if (field.getType().equals(DConfigBeanVersionType.class)
437: && Modifier.isStatic(field.getModifiers())) {
438: return (DConfigBeanVersionType) field.get(null);
439: }
440: } catch (Exception e) {
441: }
442: throw new DeploymentManagerCreationException(
443: "Unknown DConfig bean version: " + string);
444: }
445:
446: public static class TargetImpl implements Target, Comparable,
447: Serializable {
448: private static final long serialVersionUID = -7257857314911948377L;
449: private final String name;
450: private final String description;
451:
452: public TargetImpl(String name) {
453: this (name, null);
454: }
455:
456: public TargetImpl(String name, String description) {
457: if (name == null)
458: throw new NullPointerException("name is null");
459: this .name = name;
460: this .description = description;
461: }
462:
463: public String getName() {
464: return name;
465: }
466:
467: public String getDescription() {
468: return description;
469: }
470:
471: public String toString() {
472: return name;
473: }
474:
475: public boolean equals(Object o) {
476: if (this == o)
477: return true;
478: if (!(o instanceof TargetImpl))
479: return false;
480:
481: TargetImpl target = (TargetImpl) o;
482: return name.equals(target.name);
483: }
484:
485: public int hashCode() {
486: return name.hashCode();
487: }
488:
489: public int compareTo(Object o) {
490: TargetImpl target = (TargetImpl) o;
491: return name.compareTo(target.name);
492: }
493: }
494:
495: public static class TargetModuleIDImpl implements TargetModuleID,
496: Comparable, Serializable {
497: private static final long serialVersionUID = 2471961579457311472L;
498:
499: private final Target target;
500: private final String moduleId;
501: private final String webUrl;
502: private TargetModuleID parentTargetModuleId;
503: private Set<TargetModuleID> children = new TreeSet<TargetModuleID>();
504:
505: public TargetModuleIDImpl(Target target, String moduleId) {
506: this (target, moduleId, null);
507: }
508:
509: public TargetModuleIDImpl(Target target, String moduleId,
510: String webUrl) {
511: if (target == null)
512: throw new NullPointerException("target is null");
513: if (moduleId == null)
514: throw new NullPointerException("moduleId is null");
515: this .target = target;
516: this .moduleId = moduleId;
517: this .webUrl = webUrl;
518: }
519:
520: public Target getTarget() {
521: return target;
522: }
523:
524: public String getModuleID() {
525: return moduleId;
526: }
527:
528: public TargetModuleID getParentTargetModuleID() {
529: return parentTargetModuleId;
530: }
531:
532: public void setParentTargetModuleID(
533: TargetModuleIDImpl parentTargetModuleId) {
534: this .parentTargetModuleId = parentTargetModuleId;
535: parentTargetModuleId.children.add(this );
536: }
537:
538: public TargetModuleID[] getChildTargetModuleID() {
539: return children
540: .toArray(new TargetModuleID[children.size()]);
541: }
542:
543: public String getWebURL() {
544: return webUrl;
545: }
546:
547: public String toString() {
548: return target + "/" + moduleId
549: + (webUrl == null ? " " : webUrl);
550: }
551:
552: public boolean equals(Object o) {
553: if (this == o)
554: return true;
555: if (!(o instanceof TargetModuleIDImpl))
556: return false;
557:
558: TargetModuleIDImpl targetModuleID = (TargetModuleIDImpl) o;
559: return target.equals(targetModuleID.target)
560: && moduleId.equals(targetModuleID.moduleId);
561: }
562:
563: public int hashCode() {
564: int result;
565: result = target.hashCode();
566: result = 29 * result + moduleId.hashCode();
567: return result;
568: }
569:
570: public int compareTo(Object o) {
571: TargetModuleIDImpl targetModuleID = (TargetModuleIDImpl) o;
572:
573: // compare target name
574: int val = target.getName().compareTo(
575: targetModuleID.target.getName());
576: if (val != 0)
577: return val;
578:
579: // compare moduleId
580: return moduleId.compareTo(targetModuleID.moduleId);
581: }
582: }
583:
584: public class ProgressObjectImpl implements ProgressObject {
585: private final Set<TargetModuleID> targetModuleIds;
586: private final ProgressEvent event;
587: private final DeploymentStatus deploymentStatus;
588:
589: public ProgressObjectImpl(CommandType command,
590: Set<TargetModuleID> targetModuleIds) {
591: this .targetModuleIds = targetModuleIds;
592: deploymentStatus = new DeploymentStatusImpl(command);
593: event = new ProgressEvent(this , null, deploymentStatus);
594: }
595:
596: public ProgressObjectImpl(CommandType command,
597: Exception exception) {
598: this .targetModuleIds = null;
599: deploymentStatus = new DeploymentStatusImpl(command,
600: exception);
601: event = new ProgressEvent(this , null, deploymentStatus);
602: }
603:
604: public synchronized TargetModuleID[] getResultTargetModuleIDs() {
605: return targetModuleIds
606: .toArray(new TargetModuleID[targetModuleIds.size()]);
607: }
608:
609: public synchronized DeploymentStatus getDeploymentStatus() {
610: return deploymentStatus;
611: }
612:
613: public ClientConfiguration getClientConfiguration(
614: TargetModuleID id) {
615: return null;
616: }
617:
618: public boolean isCancelSupported() {
619: return false;
620: }
621:
622: public void cancel() throws OperationUnsupportedException {
623: throw new OperationUnsupportedException(
624: "cancel is not supported");
625: }
626:
627: public boolean isStopSupported() {
628: return false;
629: }
630:
631: public void stop() throws OperationUnsupportedException {
632: throw new OperationUnsupportedException(
633: "stop is not supported");
634: }
635:
636: public void addProgressListener(ProgressListener pol) {
637: pol.handleProgressEvent(event);
638: }
639:
640: public void removeProgressListener(ProgressListener pol) {
641: }
642:
643: }
644:
645: public static class DeploymentStatusImpl implements
646: DeploymentStatus {
647: private final CommandType command;
648: private final StateType state;
649: private final String message;
650:
651: public DeploymentStatusImpl(CommandType command) {
652: this .command = command;
653: this .state = StateType.COMPLETED;
654: this .message = null;
655: }
656:
657: public DeploymentStatusImpl(CommandType command,
658: Exception exception) {
659: this .command = command;
660: this .state = StateType.FAILED;
661:
662: StringWriter writer = new StringWriter();
663: exception.printStackTrace(new PrintWriter(writer, true));
664: this .message = writer.toString();
665: }
666:
667: public CommandType getCommand() {
668: return command;
669: }
670:
671: public ActionType getAction() {
672: return ActionType.EXECUTE;
673: }
674:
675: public String getMessage() {
676: return message;
677: }
678:
679: public StateType getState() {
680: return state;
681: }
682:
683: public boolean isRunning() {
684: return StateType.RUNNING.equals(state);
685: }
686:
687: public boolean isCompleted() {
688: return StateType.COMPLETED.equals(state);
689: }
690:
691: public boolean isFailed() {
692: return StateType.FAILED.equals(state);
693: }
694:
695: public String toString() {
696: StringBuffer buf = new StringBuffer();
697: buf.append("DeploymentStatus[").append(command).append(',');
698: buf.append(state);
699: if (message != null) {
700: buf.append(',').append(message);
701: }
702: buf.append(']');
703: return buf.toString();
704: }
705: }
706: }
|