1 /* |
1 /* |
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
2 * Copyright (c) 2009 - 2010 Nokia Corporation and/or its subsidiary(-ies). |
3 * All rights reserved. |
3 * All rights reserved. |
4 * This component and the accompanying materials are made available |
4 * This component and the accompanying materials are made available |
5 * under the terms of "Eclipse Public License v1.0" |
5 * under the terms of "Eclipse Public License v1.0" |
6 * which accompanies this distribution, and is available |
6 * which accompanies this distribution, and is available |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
19 package com.nokia.mj.impl.rt.midp; |
19 package com.nokia.mj.impl.rt.midp; |
20 |
20 |
21 import java.io.InputStream; |
21 import java.io.InputStream; |
22 import java.io.InputStreamReader; |
22 import java.io.InputStreamReader; |
23 import java.io.IOException; |
23 import java.io.IOException; |
|
24 import java.util.Hashtable; |
24 import java.util.Timer; |
25 import java.util.Timer; |
25 import java.util.TimerTask; |
26 import java.util.TimerTask; |
26 |
27 |
27 import com.nokia.mj.impl.rt.utils.ExtensionUtil; |
28 import com.nokia.mj.impl.rt.utils.ExtensionUtil; |
28 |
29 |
45 |
46 |
46 import com.nokia.mj.impl.utils.LineReader; |
47 import com.nokia.mj.impl.utils.LineReader; |
47 import com.nokia.mj.impl.utils.TaskQueue; |
48 import com.nokia.mj.impl.utils.TaskQueue; |
48 import com.nokia.mj.impl.utils.Uid; |
49 import com.nokia.mj.impl.utils.Uid; |
49 import com.nokia.mj.impl.utils.StartUpTrace; |
50 import com.nokia.mj.impl.utils.StartUpTrace; |
|
51 |
50 |
52 |
51 /** |
53 /** |
52 * A core of the MIDP life cycle. This class controls the life time of the |
54 * A core of the MIDP life cycle. This class controls the life time of the |
53 * MIDlet. |
55 * MIDlet. |
54 * <p> |
56 * <p> |
173 * the url contains MIDlet argument 'PromptAppStartup' |
175 * the url contains MIDlet argument 'PromptAppStartup' |
174 */ |
176 */ |
175 private boolean mAutoinvocationFromUrl = false; |
177 private boolean mAutoinvocationFromUrl = false; |
176 |
178 |
177 /** |
179 /** |
|
180 * PropertyKeys that are not listed in the values of Jad / Manifest |
|
181 * attribute Nokia-MIDlet-Launch-Params |
|
182 */ |
|
183 private Hashtable mAcceptedUserProperties; |
|
184 |
|
185 /** |
178 * Flag for identifying whether the MIDlet is a standalone MIDlet. |
186 * Flag for identifying whether the MIDlet is a standalone MIDlet. |
179 */ |
187 */ |
180 private boolean mStandAlone = false; |
188 private boolean mStandAlone = false; |
181 |
189 |
182 /*** ----------------------------- PRIVATE ---------------------------- */ |
190 /*** ----------------------------- PRIVATE ---------------------------- */ |
368 JvmInternal.setSystemProperty("com.nokia.mid.cmdline.instance", |
376 JvmInternal.setSystemProperty("com.nokia.mid.cmdline.instance", |
369 Integer.toString(mRelaunchCount + 1)); |
377 Integer.toString(mRelaunchCount + 1)); |
370 if (Log.mOn) |
378 if (Log.mOn) |
371 Log.logI("MIDlet launch count is : " + Integer.toString(mRelaunchCount + 1)); |
379 Log.logI("MIDlet launch count is : " + Integer.toString(mRelaunchCount + 1)); |
372 |
380 |
373 // Update possible MIDlet arguments |
381 if (applicationArgs != null) |
374 setMidletArguments(applicationArgs); |
382 { |
|
383 JvmInternal.setSystemProperty("com.nokia.mid.cmdline", applicationArgs); |
|
384 } |
375 |
385 |
376 if (mState == PRE_INIT_DONE) |
386 if (mState == PRE_INIT_DONE) |
377 { |
387 { |
378 // We were waiting in prewarmed state the launch request |
388 // We were waiting in prewarmed state the launch request |
379 // and now got it. |
389 // and now got it. |
382 mTaskQueue.addTask(new LifeCycleTask(LifeCycleTask.START_REQUEST, |
392 mTaskQueue.addTask(new LifeCycleTask(LifeCycleTask.START_REQUEST, |
383 LifeCycleTask.PRE_WARM_START)); |
393 LifeCycleTask.PRE_WARM_START)); |
384 } |
394 } |
385 else |
395 else |
386 { |
396 { |
|
397 // Update possible MIDlet arguments |
|
398 setMidletArguments(); |
387 // Bring the MIDlet to foreground |
399 // Bring the MIDlet to foreground |
388 CoreUi.foregroundRequest(); |
400 CoreUi.foregroundRequest(); |
389 } |
401 } |
390 } |
402 } |
391 |
403 |
792 if ((encodedMidletArgs != null) && (encodedMidletArgs.length() > 0)) |
804 if ((encodedMidletArgs != null) && (encodedMidletArgs.length() > 0)) |
793 { |
805 { |
794 // Decode arguments |
806 // Decode arguments |
795 String midletArgs = decodeArgs(encodedMidletArgs); |
807 String midletArgs = decodeArgs(encodedMidletArgs); |
796 |
808 |
797 // Parse them |
809 // Resetting the system property after decoding. |
798 setMidletArguments(midletArgs); |
810 JvmInternal.setSystemProperty("com.nokia.mid.cmdline", midletArgs); |
799 } |
811 } |
800 |
812 |
801 // If the runtime is set to pre warmed state, then the |
813 // If the runtime is set to pre warmed state, then the |
802 // value of the prewarm flag contans the process id which |
814 // value of the prewarm flag contans the process id which |
803 // is needed by Captain for identification. |
815 // is needed by Captain for identification. |
847 * Decode string in a private format that was safe to pass to Java side |
859 * Decode string in a private format that was safe to pass to Java side |
848 * as a Java system property. |
860 * as a Java system property. |
849 * Native side function java::util::runtime::MidpRuntimeStarter::encodeArgs() |
861 * Native side function java::util::runtime::MidpRuntimeStarter::encodeArgs() |
850 * was used to encode the string |
862 * was used to encode the string |
851 * |
863 * |
852 * @param args original wstring |
864 * @param encodedArgs encoded arguments |
853 * @return encoded wstring |
865 * @return decoded argument string |
854 */ |
866 */ |
855 private String decodeArgs(String encodedArgs) |
867 private String decodeArgs(String encodedArgs) |
856 { |
868 { |
857 StringBuffer res = new StringBuffer(); |
869 StringBuffer res = new StringBuffer(); |
858 int idx = encodedArgs.indexOf('%'); |
870 int idx = 0; |
859 int cur = 0; |
871 int len = encodedArgs.length(); |
860 |
872 char t; |
861 while (idx != -1) |
873 |
862 { |
874 // Decoding is done in blocks of 4 or 2 characters. |
863 // Add all characters up to but not including the '%' char |
875 // Possible extra chars are ignored |
864 // to final result string |
876 |
865 if ((idx - cur) > 0) |
877 while (idx < len) |
866 { |
878 { |
867 res.append(encodedArgs.substring(cur, idx)); |
879 t = encodedArgs.charAt(idx); |
868 } |
880 if (t < 'a') |
869 |
881 { |
870 // Decode all special sequences 'X%' in same way. |
882 if (idx + 4 >= len) |
871 // "X%" -> "X", so skip "%" |
883 break; |
872 // Note that "%%" is decoded to "%" |
884 // decode one 16-bit char |
873 cur = idx + 1; |
885 char a = (char)(t - 'A'); |
874 idx = encodedArgs.indexOf('%', cur + 1); |
886 char b = (char)(encodedArgs.charAt(idx+1) - 'A'); |
875 } |
887 char c = (char)(encodedArgs.charAt(idx+2) - 'A'); |
876 |
888 char d = (char)(encodedArgs.charAt(idx+3) - 'A'); |
877 // Add characters after last special character if any |
889 char r = (char)(((a<<12)+(b<<8)+(c<<4)+d)); |
878 res.append(encodedArgs.substring(cur, encodedArgs.length())); |
890 res.append(r); |
|
891 idx = idx + 4; |
|
892 } |
|
893 else |
|
894 { |
|
895 if (idx + 2 >= len) |
|
896 break; |
|
897 // decode one 8-bit char |
|
898 char a = (char)(t - 'a'); |
|
899 char b = (char)(encodedArgs.charAt(idx+1) - 'a'); |
|
900 char r = (char)((a<<4)+b); |
|
901 res.append(r); |
|
902 idx = idx + 2; |
|
903 } |
|
904 } |
879 |
905 |
880 return res.toString(); |
906 return res.toString(); |
881 } |
907 } |
882 |
908 |
883 /** |
909 /** |
929 |
955 |
930 // Set the MidletInfo class to contain correct data. The data is read |
956 // Set the MidletInfo class to contain correct data. The data is read |
931 // from storage. |
957 // from storage. |
932 setMidletInfo(); |
958 setMidletInfo(); |
933 |
959 |
|
960 // If system property com.nokia.mid.cmdline has value, it contains |
|
961 // the arguments for the current MIDlet. |
|
962 setMidletArguments(); |
|
963 |
934 if (mPrewarmStart) |
964 if (mPrewarmStart) |
935 { |
965 { |
936 // Get the recorded heap size from previous run. |
966 // Get the recorded heap size from previous run. |
937 int targetHeapSize = MemoryLogger.getOldHeapSizeToExpand(); |
967 int targetHeapSize = MemoryLogger.getOldHeapSizeToExpand(); |
938 |
968 |
1114 } |
1144 } |
1115 |
1145 |
1116 /** |
1146 /** |
1117 * Parse the MIDlet arguments given as parameter and set them |
1147 * Parse the MIDlet arguments given as parameter and set them |
1118 * to system properties so that MIDlet can access them. |
1148 * to system properties so that MIDlet can access them. |
1119 * |
1149 */ |
1120 * @param applicationArgs the MIDlet arguments, can be empty |
1150 private void setMidletArguments() |
1121 */ |
1151 { |
1122 private void setMidletArguments(String applicationArgs) |
1152 String applicationArgs = System.getProperty("com.nokia.mid.cmdline"); |
1123 { |
1153 |
1124 if (applicationArgs == null) |
1154 if (applicationArgs != null && applicationArgs.length() > 0) |
1125 { |
|
1126 applicationArgs = ""; |
|
1127 } |
|
1128 JvmInternal.setSystemProperty("com.nokia.mid.cmdline", applicationArgs); |
|
1129 |
|
1130 if (applicationArgs.length() > 0) |
|
1131 { |
1155 { |
1132 if (Log.mOn) |
1156 if (Log.mOn) |
1133 Log.logI("MIDlet arguments are : " + applicationArgs); |
1157 Log.logI("MIDlet arguments are : " + applicationArgs); |
1134 |
1158 |
1135 // parse args and set individual system properties |
1159 // parse args and set individual system properties |
1140 StringBuffer argBuf = new StringBuffer(); |
1164 StringBuffer argBuf = new StringBuffer(); |
1141 String arg; |
1165 String arg; |
1142 String propertyKey; |
1166 String propertyKey; |
1143 String propertyValue; |
1167 String propertyValue; |
1144 mAutoinvocationFromUrl = false; |
1168 mAutoinvocationFromUrl = false; |
|
1169 if (mAcceptedUserProperties == null) |
|
1170 { |
|
1171 // Doing intialization only once. |
|
1172 String launchParams = |
|
1173 ApplicationInfoImpl.getMidletInfo().getAttribute("Nokia-MIDlet-Launch-Params"); |
|
1174 mAcceptedUserProperties = split(launchParams, ","); |
|
1175 } |
1145 |
1176 |
1146 do |
1177 do |
1147 { |
1178 { |
1148 argBuf.setLength(0); |
1179 argBuf.setLength(0); |
1149 idx = applicationArgs.indexOf(";", cur); |
1180 idx = applicationArgs.indexOf(";", cur); |
1181 // The property has also a value. |
1211 // The property has also a value. |
1182 propertyKey = arg.substring(0, indEq); |
1212 propertyKey = arg.substring(0, indEq); |
1183 propertyValue = arg.substring(indEq + 1); |
1213 propertyValue = arg.substring(indEq + 1); |
1184 } |
1214 } |
1185 |
1215 |
1186 if (propertyKey.equals("com.nokia.mid.cmdline.param.PromptAppStartup")) |
1216 if (propertyKey.equals("PromptAppStartup")) |
1187 { |
1217 { |
1188 mAutoinvocationFromUrl = true; |
1218 mAutoinvocationFromUrl = true; |
1189 if (Log.mOn) |
1219 if (Log.mOn) |
1190 Log.logI("MIDlet had argument PromptAppStartup"); |
1220 Log.logI("MIDlet had argument PromptAppStartup"); |
1191 } |
1221 } |
1192 |
1222 |
1193 JvmInternal.setSystemProperty(propertyKey, propertyValue); |
1223 if (mAcceptedUserProperties.get(propertyKey) != null) |
|
1224 { |
|
1225 JvmInternal.setUserProperty(propertyKey, propertyValue); |
|
1226 } |
1194 |
1227 |
1195 cur = idx + 1; |
1228 cur = idx + 1; |
1196 } |
1229 } |
1197 while ((idx != -1) && (cur < applicationArgs.length())); |
1230 while ((idx != -1) && (cur < applicationArgs.length())); |
1198 } |
1231 } |
|
1232 } |
|
1233 |
|
1234 /** |
|
1235 * Split a string into Hashtable. This util method splits the given |
|
1236 * string separated by given separator into Hashtable so that tokens |
|
1237 * are keys and values are just empty Strings. Before adding the tokens |
|
1238 * into hashtable those are trimmed. |
|
1239 * |
|
1240 * @str String to split. |
|
1241 * @separator A separator that separates the tokens. |
|
1242 */ |
|
1243 static Hashtable split(String str, String separator) |
|
1244 { |
|
1245 Hashtable ht = new Hashtable(); |
|
1246 if (separator != null) |
|
1247 { |
|
1248 int separatorLen = separator.length(); |
|
1249 if (str != null && separatorLen > 0) |
|
1250 { |
|
1251 int index = str.indexOf(separator); |
|
1252 while (index != -1) |
|
1253 { |
|
1254 String token = str.substring(0,index).trim(); |
|
1255 ht.put(token, ""); |
|
1256 str = str.substring(index + separatorLen); |
|
1257 index = str.indexOf(separator); |
|
1258 } |
|
1259 } |
|
1260 } |
|
1261 if (str != null) |
|
1262 { |
|
1263 str = str.trim(); |
|
1264 if (str.length() > 0) |
|
1265 { |
|
1266 // add token after last separator |
|
1267 ht.put(str, ""); |
|
1268 } |
|
1269 } |
|
1270 return ht; |
1199 } |
1271 } |
1200 |
1272 |
1201 /** |
1273 /** |
1202 * Class for extending the TimerTask. This is for the shut down timer. |
1274 * Class for extending the TimerTask. This is for the shut down timer. |
1203 */ |
1275 */ |