001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.installer;
028:
029: import java.io.*;
030:
031: import javax.microedition.rms.*;
032:
033: import com.sun.midp.i18n.Resource;
034:
035: import com.sun.midp.i18n.ResourceConstants;
036:
037: import com.sun.midp.main.MIDletSuiteUtils;
038:
039: import com.sun.midp.midlet.MIDletStateHandler;
040:
041: import com.sun.midp.midletsuite.MIDletInfo;
042: import com.sun.midp.midletsuite.MIDletSuiteStorage;
043: import com.sun.midp.midlet.MIDletSuite;
044: import com.sun.midp.configurator.Constants;
045:
046: import com.sun.midp.log.Logging;
047: import com.sun.midp.log.LogChannels;
048:
049: /**
050: * Installs/Updates a test suite, runs the first MIDlet in the suite in a loop
051: * specified number of iterations or until the new version of the suite is not
052: * found, then removes the suite.
053: * <p>
054: * The MIDlet uses these application properties as arguments: </p>
055: * <ol>
056: * <li>arg-0: URL for the test suite
057: * <li>arg-1: Used to override the default domain used when installing
058: * an unsigned suite. The default is maximum to allow the runtime API tests
059: * be performed automatically without tester interaction. The domain name
060: * may be followed by a colon and a list of permissions that must be allowed
061: * even if they are not listed in the MIDlet-Permissions attribute in the
062: * application descriptor file. Instead of the list a keyword "all" can be
063: * specified indicating that all permissions must be allowed, for example:
064: * operator:all.
065: * <li>arg-2: Integer number, specifying how many iterations to run
066: * the suite. If argument is not given or less then zero, then suite
067: * will be run until the new version of the suite is not found.
068: * </ol>
069: * <p>
070: * If arg-0 is not given then a form will be used to query the tester for
071: * the arguments.</p>
072: */
073: public class AutoTester extends AutoTesterBase implements
074: AutoTesterInterface {
075:
076: /** Settings database name. */
077: private static final String AUTOTEST_STORE = "autotest";
078: /** Record ID of URL. */
079: private static final int URL_RECORD_ID = 1;
080: /** Record ID of the security domain for unsigned suites. */
081: private static final int DOMAIN_RECORD_ID = 2;
082: /** Record ID of suite ID. */
083: private static final int SUITE_ID_RECORD_ID = 3;
084: /** Record ID of loopCount */
085: private static final int LOOP_COUNT_RECORD_ID = 4;
086: /** ID of installed test suite. */
087: int suiteId;
088:
089: /**
090: * Create and initialize a new auto tester MIDlet.
091: */
092: public AutoTester() {
093: super ();
094:
095: if (url != null) {
096: startBackgroundTester();
097: } else if (restoreSession()) {
098: // continuation of a previous session
099: startBackgroundTester();
100: } else {
101: /**
102: * No URL has been provided, ask the user.
103: *
104: * commandAction will subsequently call startBackgroundTester.
105: */
106: getUrl();
107: }
108: }
109:
110: /** Run the installer. */
111: public void run() {
112: installAndPerformTests(midletSuiteStorage, installer, url);
113: }
114:
115: /**
116: * Restore the data from the last session.
117: *
118: * @return true if there was data saved from the last session
119: */
120: public boolean restoreSession() {
121: RecordStore settings = null;
122: ByteArrayInputStream bas;
123: DataInputStream dis;
124: byte[] data;
125:
126: try {
127: settings = RecordStore.openRecordStore(AUTOTEST_STORE,
128: false);
129:
130: data = settings.getRecord(URL_RECORD_ID);
131: if (data == null) {
132: return false;
133: }
134:
135: bas = new ByteArrayInputStream(data);
136: dis = new DataInputStream(bas);
137: url = dis.readUTF();
138:
139: data = settings.getRecord(DOMAIN_RECORD_ID);
140: if (data != null && data.length > 0) {
141: bas = new ByteArrayInputStream(data);
142: dis = new DataInputStream(bas);
143: domain = dis.readUTF();
144: }
145:
146: data = settings.getRecord(SUITE_ID_RECORD_ID);
147: if (data != null && data.length > 0) {
148: bas = new ByteArrayInputStream(data);
149: dis = new DataInputStream(bas);
150: suiteId = dis.readInt();
151: }
152:
153: data = settings.getRecord(LOOP_COUNT_RECORD_ID);
154: if (data != null && data.length > 0) {
155: bas = new ByteArrayInputStream(data);
156: dis = new DataInputStream(bas);
157: loopCount = dis.readInt();
158: }
159:
160: return true;
161: } catch (RecordStoreNotFoundException rsnfe) {
162: // This normal when no initial args are given, ignore
163: } catch (Exception ex) {
164: displayException(Resource
165: .getString(ResourceConstants.EXCEPTION), ex
166: .toString());
167: } finally {
168: if (settings != null) {
169: try {
170: settings.closeRecordStore();
171: } catch (Exception ex) {
172: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
173: Logging.report(Logging.WARNING,
174: LogChannels.LC_AMS,
175: "closeRecordStore threw an Exception");
176: }
177: }
178: }
179: }
180:
181: return false;
182: }
183:
184: /**
185: * Save session data for next time.
186: *
187: * @exception if an exception occurs
188: */
189: private void saveSession() throws Exception {
190: RecordStore settings = null;
191: boolean newStore = false;
192: ByteArrayOutputStream bas;
193: DataOutputStream dos;
194: byte[] data;
195:
196: if (url == null) {
197: return;
198: }
199:
200: try {
201: settings = RecordStore
202: .openRecordStore(AUTOTEST_STORE, true);
203:
204: if (settings.getNextRecordID() == URL_RECORD_ID) {
205: newStore = true;
206: }
207:
208: bas = new ByteArrayOutputStream();
209: dos = new DataOutputStream(bas);
210: dos.writeUTF(url);
211: data = bas.toByteArray();
212:
213: if (newStore) {
214: settings.addRecord(data, 0, data.length);
215: } else {
216: settings.setRecord(URL_RECORD_ID, data, 0, data.length);
217: }
218:
219: bas.reset();
220: dos.writeUTF(domain);
221: data = bas.toByteArray();
222:
223: if (newStore) {
224: settings.addRecord(data, 0, data.length);
225: } else {
226: settings.setRecord(DOMAIN_RECORD_ID, data, 0,
227: data.length);
228: }
229:
230: bas.reset();
231: dos.writeInt(suiteId);
232: data = bas.toByteArray();
233:
234: if (newStore) {
235: settings.addRecord(data, 0, data.length);
236: } else {
237: settings.setRecord(SUITE_ID_RECORD_ID, data, 0,
238: data.length);
239: }
240:
241: bas.reset();
242: dos.writeInt(loopCount);
243: data = bas.toByteArray();
244:
245: if (newStore) {
246: settings.addRecord(data, 0, data.length);
247: } else {
248: settings.setRecord(LOOP_COUNT_RECORD_ID, data, 0,
249: data.length);
250: }
251: } finally {
252: if (settings != null) {
253: try {
254: settings.closeRecordStore();
255: } catch (Exception ex) {
256: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
257: Logging.report(Logging.WARNING,
258: LogChannels.LC_AMS,
259: "closeRecordStore threw an exception");
260: }
261: }
262: }
263: }
264: }
265:
266: /** End the testing session. */
267: private void endSession() {
268: try {
269: RecordStore.deleteRecordStore(AUTOTEST_STORE);
270: } catch (Throwable ex) {
271: // ignore
272: }
273:
274: notifyDestroyed();
275: }
276:
277: /**
278: * Installs and performs the tests.
279: *
280: * @param midletSuiteStorage MIDletSuiteStorage object
281: * @param inp_installer Installer object
282: * @param inp_url URL of the test suite
283: */
284: public void installAndPerformTests(
285: MIDletSuiteStorage midletSuiteStorage,
286: Installer inp_installer, String inp_url) {
287:
288: MIDletInfo midletInfo;
289: String message = null;
290:
291: if (loopCount != 0) {
292: try {
293: // force an overwrite and remove the RMS data
294: suiteId = inp_installer.installJad(inp_url,
295: Constants.INTERNAL_STORAGE_ID, true, true,
296: installListener);
297:
298: midletInfo = getFirstMIDletOfSuite(suiteId,
299: midletSuiteStorage);
300: MIDletSuiteUtils.execute(suiteId, midletInfo.classname,
301: midletInfo.name);
302:
303: // We want auto tester MIDlet to run after the test is run.
304: MIDletSuiteUtils.setLastSuiteToRun(MIDletStateHandler
305: .getMidletStateHandler().getMIDletSuite()
306: .getID(), getClass().getName(), null, null);
307:
308: if (loopCount > 0) {
309: loopCount -= 1;
310: }
311: saveSession();
312: notifyDestroyed();
313: return;
314: } catch (Throwable t) {
315: handleInstallerException(suiteId, t);
316: }
317: }
318:
319: if (midletSuiteStorage != null
320: && suiteId != MIDletSuite.UNUSED_SUITE_ID) {
321: try {
322: midletSuiteStorage.remove(suiteId);
323: } catch (Throwable ex) {
324: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
325: Logging.report(Logging.WARNING, LogChannels.LC_AMS,
326: "Throwable in remove");
327: }
328: }
329: }
330:
331: endSession();
332: }
333: }
|