001: /********************************************************************************
002: * CruiseControl, a Continuous Integration Toolkit
003: * Copyright (c) 2001-2003, ThoughtWorks, Inc.
004: * 651 W Washington Ave. Suite 600
005: * Chicago, IL 60661 USA
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * + Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * + Redistributions in binary form must reproduce the above
016: * copyright notice, this list of conditions and the following
017: * disclaimer in the documentation and/or other materials provided
018: * with the distribution.
019: *
020: * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
021: * names of its contributors may be used to endorse or promote
022: * products derived from this software without specific prior
023: * written permission.
024: *
025: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
029: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
030: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
031: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
032: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
033: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
034: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036: ********************************************************************************/package net.sourceforge.cruisecontrol.bootstrappers;
037:
038: import com.trinem.harvest.hsdkwrap.JCaCheckoutWrap;
039: import com.trinem.harvest.hsdkwrap.JCaConstWrap;
040: import com.trinem.harvest.hsdkwrap.JCaContextWrap;
041: import com.trinem.harvest.hsdkwrap.JCaHarvestWrap;
042: import com.trinem.harvest.hsdkwrap.JCaHarvestLogStreamWrap;
043: import com.trinem.harvest.hsdkwrap.JCaVersionChooserWrap;
044: import com.trinem.harvest.hsdkwrap.IJCaLogStreamListenerImpl; // import
045: // com.trinem.harvest.hsdkwrap.hutils.JCaAttrKeyWrap;
046: import com.trinem.harvest.hsdkwrap.hutils.JCaHarvestExceptionWrap;
047:
048: import net.sourceforge.cruisecontrol.Bootstrapper;
049: import net.sourceforge.cruisecontrol.CruiseControlException;
050: import net.sourceforge.cruisecontrol.util.ValidationHelper;
051:
052: import org.apache.log4j.Logger;
053:
054: /**
055: * BootStrapper for CA's AllFusion Harvest Change Manager.
056: *
057: * This BootStrapper class is used to connect to Harvest to retrieve files
058: * before the build is started. It has a number of properties which must be set
059: * in order to connect to Harvest. It also provides a mechanism to pipe Harvest
060: * errors through into the CruiseControl log.
061: *
062: * @author <a href="mailto:info@trinem.com">Trinem Consulting Ltd</a>
063: */
064: public class AllFusionHarvestBootstrapper implements Bootstrapper {
065:
066: private JCaHarvestWrap harvest = null;
067:
068: private String broker = null;
069: private String username = null;
070: private String password = null;
071:
072: private String project = null;
073: private String state = null;
074:
075: private String process = null;
076: private String clientPath = null;
077: private String viewPath = null;
078: private String filename = null;
079:
080: private boolean loggedIn = false;
081:
082: private JCaHarvestLogStreamWrap logstream = null;
083:
084: private static Logger log = Logger
085: .getLogger(AllFusionHarvestBootstrapper.class);
086:
087: /**
088: * Default constructor. Creates a new uninitialise Bootstrapper.
089: */
090: public AllFusionHarvestBootstrapper() {
091: }
092:
093: /**
094: * Sets the Harvest Broker for all calls to HSDK.
095: *
096: * @param broker
097: * Harvest Broker to use.
098: */
099: public void setBroker(String broker) {
100: log.debug("Broker: " + broker);
101: this .broker = broker;
102: }
103:
104: /**
105: * Sets the Harvest username for all calls to HSDK.
106: *
107: * @param username
108: * Harvest username to use.
109: */
110: public void setUsername(String username) {
111: this .username = username;
112: }
113:
114: /**
115: * Sets the Harvest password for all calls to HSDK.
116: *
117: * @param password
118: * Harvest password to use.
119: */
120: public void setPassword(String password) {
121: this .password = password;
122: }
123:
124: /**
125: * Sets the Harvest project for all calls to HSDK.
126: *
127: * @param project
128: * Harvest project to use.
129: */
130: public void setProject(String project) {
131: this .project = project;
132: }
133:
134: /**
135: * Sets the Harvest state for all calls to HSDK.
136: *
137: * @param state
138: * Harvest state to use.
139: */
140: public void setState(String state) {
141: this .state = state;
142: }
143:
144: /**
145: * Sets the name of the process to use when making calls to HSDK.
146: *
147: * @param process
148: * String indicating the process name.
149: */
150: public void setProcess(String process) {
151: this .process = process;
152: }
153:
154: /**
155: * Sets the view path to use when making calls to HSDK.
156: *
157: * @param viewPath
158: * String indicating the view path.
159: */
160: public void setViewpath(String viewPath) {
161: this .viewPath = viewPath;
162: }
163:
164: /**
165: * Sets the client path to use when making calls to HSDK.
166: *
167: * @param clientPath
168: * String indicating the client path.
169: */
170: public void setClientpath(String clientPath) {
171: this .clientPath = clientPath;
172: }
173:
174: /**
175: * Sets the filename to update.
176: *
177: * @param filename
178: * String indicating the filename.
179: */
180: public void setFile(String filename) {
181: this .filename = filename;
182: }
183:
184: /**
185: * Internal method which connects to Harvest using the details provided.
186: */
187: protected boolean login() {
188:
189: if (loggedIn) {
190: return true;
191: }
192:
193: harvest = new JCaHarvestWrap(broker);
194:
195: logstream = new JCaHarvestLogStreamWrap();
196: logstream.addLogStreamListener(new MyLogStreamListener());
197:
198: harvest.setStaticLog(logstream);
199: harvest.setLog(logstream);
200:
201: if (harvest.login(username, password) != 0) {
202: log.error("Login failed: " + harvest.getLastMessage());
203: return false;
204: }
205:
206: loggedIn = true;
207: return true;
208: }
209:
210: /**
211: * Internal method which disconnects from Harvest.
212: */
213: protected void logout() {
214: try {
215: harvest.logout();
216: } catch (JCaHarvestExceptionWrap e) {
217: log.error(e.getMessage());
218: }
219: }
220:
221: // From Bootstrapper
222: /**
223: * Standard Bootstrapper validation method. Throws an exception if any of
224: * the required properties are not set.
225: */
226: public void validate() throws CruiseControlException {
227:
228: ValidationHelper.assertIsSet(username, "username", this
229: .getClass());
230: ValidationHelper.assertIsSet(password, "password", this
231: .getClass());
232: ValidationHelper.assertIsSet(broker, "broker", this .getClass());
233: ValidationHelper.assertIsSet(state, "state", this .getClass());
234: ValidationHelper.assertIsSet(project, "project", this
235: .getClass());
236: ValidationHelper.assertIsSet(process, "process", this
237: .getClass());
238: ValidationHelper.assertIsSet(clientPath, "clientPath", this
239: .getClass());
240: ValidationHelper.assertIsSet(viewPath, "viewPath", this
241: .getClass());
242: ValidationHelper.assertIsSet(filename, "filename", this
243: .getClass());
244: }
245:
246: /**
247: * Update the specified file.
248: */
249: public void bootstrap() {
250:
251: log.debug("bootstrap()");
252:
253: if (!login()) {
254: return;
255: }
256:
257: try {
258: JCaContextWrap context = harvest.getContext();
259: context.setProject(project);
260: context.setState(state);
261:
262: if (!context.setCheckout(process)) {
263: log.error("No checkout process named \"" + process
264: + "\" in this project/state");
265: return;
266: }
267: if (!context
268: .isProcessSet(JCaConstWrap.HAR_CHECKOUT_PROCESS_TYPE)) {
269: log.error("No checkout process in this project/state");
270: return;
271: }
272:
273: JCaCheckoutWrap coproc = context.getCheckout();
274: coproc.setCheckoutMode(JCaConstWrap.CO_MODE_SYNCHRONIZE);
275: coproc
276: .setPathOption(JCaConstWrap.CO_OPTION_PRESERVE_AND_CREATE);
277: coproc.setReplaceFile(true);
278: coproc.setClientDir(clientPath);
279: coproc.setViewPath(viewPath);
280: coproc.setShareWorkDir(true);
281: coproc.setUseCITimeStamp(true);
282:
283: JCaVersionChooserWrap vc = context.getVersionChooser();
284:
285: vc.clear();
286: vc.setRecursive(true);
287: vc
288: .setVersionItemOption(JCaConstWrap.VERSION_FILTER_ITEM_BOTH);
289: vc
290: .setVersionOption(JCaConstWrap.VERSION_FILTER_LATEST_IN_VIEW);
291: vc
292: .setVersionStatusOption(JCaConstWrap.VERSION_FILTER_ALL_TAG);
293: vc.setBranchOption(JCaConstWrap.BRANCH_FILTER_TRUNK_ONLY);
294: vc.setItemName(filename);
295:
296: vc.execute();
297:
298: /* JCaContainerWrap versionList = */vc.getVersionList();
299:
300: /*
301: * int numVers = versionList.isEmpty() ? 0 :
302: * versionList.getKeyElementCount(JCaAttrKeyWrap.CA_ATTRKEY_NAME);
303: *
304: * for (int n = 0; n < numVers; n++) {
305: * System.out.println(versionList.getString(JCaAttrKeyWrap.CA_ATTRKEY_NAME,
306: * n) + ";" +
307: * versionList.getString(JCaAttrKeyWrap.CA_ATTRKEY_MAPPED_VERSION_NAME,
308: * n) + ";" +
309: * versionList.getString(JCaAttrKeyWrap.CA_ATTRKEY_VERSION_STATUS,
310: * n));
311: * }
312: */
313:
314: coproc.execute();
315:
316: } catch (JCaHarvestExceptionWrap e) {
317: log.error(e.toString() /* , getLocation() */);
318: // e.printStackTrace();
319: }
320: }
321:
322: /**
323: * Simple LogStream Listener class which interprets the message serverity
324: * level of Harvest messages and reports them to the CruiseControl log.
325: *
326: * @author <a href="mailto:info@trinem.com">Trinem Consulting Ltd</a>
327: */
328: public class MyLogStreamListener implements
329: IJCaLogStreamListenerImpl {
330:
331: // From IJCaLogStreamListenerImpl
332: /**
333: * Takes the given message from Harvest, figures out its severity and
334: * reports it back to CruiseControl.
335: *
336: * @param message
337: * The message to process.
338: */
339: public void handleMessage(String message) {
340:
341: int level = JCaHarvestLogStreamWrap
342: .getSeverityLevel(message);
343:
344: // Convert Harvest level to log4j level
345: switch (level) {
346: case JCaHarvestLogStreamWrap.OK:
347: log.debug(message);
348: break;
349: case JCaHarvestLogStreamWrap.INFO:
350: log.info(message);
351: break;
352: case JCaHarvestLogStreamWrap.WARNING:
353: log.warn(message);
354: break;
355: case JCaHarvestLogStreamWrap.ERROR:
356: log.error(message);
357: break;
358: default:
359: }
360: }
361: }
362: }
|