Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.codename1.io;
import com.codename1.compat.java.util.Objects;
import com.codename1.impl.CodenameOneThread;
import com.codename1.ui.Command;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.TextArea;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.io.FileSystemStorage;
import com.codename1.ui.Dialog;
import com.codename1.ui.layouts.BorderLayout;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
/**
* Pluggable logging framework that allows a developer to log into storage
* using the file connector API. It is highly recommended to use this
* class coupled with Netbeans preprocessing tags to reduce its overhead
* completely in runtime.
*
* @author Shai Almog
*/
public class Log {
private static boolean crashBound;
/**
* Constant indicating the logging level Debug is the default and the lowest level
* followed by info, warning and error
*/
public static final int DEBUG = 1;
/**
* Constant indicating the logging level Debug is the default and the lowest level
* followed by info, warning and error
*/
public static final int INFO = 2;
/**
* Constant indicating the logging level Debug is the default and the lowest level
* followed by info, warning and error
*/
public static final int WARNING = 3;
/**
* Constant indicating the logging level Debug is the default and the lowest level
* followed by info, warning and error
*/
public static final int ERROR = 4;
private int level = DEBUG;
private static Log instance = new Log();
private long zeroTime = System.currentTimeMillis();
private Writer output;
private boolean fileWriteEnabled = false;
private String fileURL = null;
private boolean logDirty;
/**
* Indicates that log reporting to the cloud should be disabled
*/
public static int REPORTING_NONE = 0;
/**
* Indicates that log reporting to the cloud should occur regardless of whether an error occurred
*/
public static int REPORTING_DEBUG = 1;
/**
* Indicates that log reporting to the cloud should occur only if an error occurred
*/
public static int REPORTING_PRODUCTION = 3;
private int reporting = REPORTING_NONE;
private static boolean initialized;
/**
* Indicates the level of log reporting, this allows developers to send device logs to the cloud
* thus tracking crashes or functionality in the device.
* @param level one of REPORTING_NONE, REPORTING_DEBUG, REPORTING_PRODUCTION
*/
public static void setReportingLevel(int level) {
instance.reporting = level;
}
/**
* Indicates the level of log reporting, this allows developers to send device logs to the cloud
* thus tracking crashes or functionality in the device.
* @return one of REPORTING_NONE, REPORTING_DEBUG, REPORTING_PRODUCTION
*/
public static int getReportingLevel() {
return instance.reporting;
}
/**
* Prevent new Log() syntax. Use getInstance()
*/
protected Log() {}
/**
* Returns a server generated unique device id that is cached locally and is only valid per application.
* Notice that this device id is specific to your application and to a specific install, it is guaranteed
* to be completely unique or -1 if unavailable (which can be due to a network error). Warning: this
* method might block while accessing the server!s
* @return a unique device id
* @deprecated this will no longer work. Use {@link #getUniqueDeviceKey()}
*/
public static long getUniqueDeviceId() {
return -1;
}
/**
* Returns a server generated unique device id that is cached locally and is only valid per application.
* Notice that this device id is specific to your application and to a specific install, it is guaranteed
* to be completely unique or null if unavailable (which can be due to a network error). Warning: this
* method might block while accessing the server!s
* @return a unique device id
*/
public static String getUniqueDeviceKey() {
String devId = Preferences.get("DeviceKey__$", null);
if(devId != null) {
return devId;
}
devId = Preferences.get("UDeviceKey__$", null);
if(devId != null) {
return devId;
}
String buildKey = Display.getInstance().getProperty("build_key", null);
if(buildKey == null) {
buildKey = "";
}
// request the device id from the server
com.codename1.io.ConnectionRequest r = new com.codename1.io.ConnectionRequest() {
protected void readResponse(java.io.InputStream input) throws java.io.IOException {
com.codename1.io.Preferences.set("UDeviceKey__$", Util.readToString(input));
}
protected void handleErrorResponseCode(int code, String message) {
System.out.print("Error in sending log to server: " + code + " " + message);
}
protected void handleException(Exception err) {
err.printStackTrace();
}
};
r.setPost(true);
r.setUrl(Display.getInstance().getProperty("cloudServerURL", "https://cloud.codenameone.com/register/device"));
r.addArgument("appName", Display.getInstance().getProperty("AppName", ""));
r.addArgument("buildKey", buildKey);
r.addArgument("builtByUser",Display.getInstance().getProperty("built_by_user", ""));
r.addArgument("packageName", Display.getInstance().getProperty("package_name", ""));
r.addArgument("appVersion", Display.getInstance().getProperty("AppVersion", "0.1"));
r.addArgument("platformName", Display.getInstance().getPlatformName());
//r.addArgument("u", Display.getInstance().getProperty("udid", ""));
com.codename1.io.NetworkManager.getInstance().addToQueueAndWait(r);
return Preferences.get("UDeviceKey__$", null);
}
/**
* Sends the current log to the cloud. Notice that this method is synchronous and
* returns only when the sending completes
*/
public static void sendLog() {
sendLogImpl(true);
}
/**
* Sends the current log to the cloud and returns immediately
*/
public static void sendLogAsync() {
sendLogImpl(true);
}
/**
* Sends the current log to the cloud regardless of the reporting level
*/
private static void sendLogImpl(boolean sync) {
try {
// this can cause a crash
if(!Display.isInitialized()) {
return;
}
if(!instance.logDirty) {
return;
}
instance.logDirty = false;
String devId = getUniqueDeviceKey();
if(devId == null) {
if(Display.getInstance().isSimulator()) {
Dialog.show("Send Log Error", "Device Not Registered: Sending a log from an unregistered device is impossible", "OK", null);
} else {
Log.p("Device Not Registered: Sending a log from an unregistered device is impossible");
}
return;
}
ConnectionRequest r = new ConnectionRequest();
r.setPost(false);
MultipartRequest m = new MultipartRequest();
m.setUrl("https://crashreport.codenameone.com/CrashReporterEmail/sendCrashReport");
byte[] read = Util.readInputStream(Storage.getInstance().createInputStream("CN1Log__$"));
m.addArgument("i", "" + devId);
m.addArgument("u",Display.getInstance().getProperty("built_by_user", ""));
m.addArgument("p", Display.getInstance().getProperty("package_name", ""));
m.addArgument("v", Display.getInstance().getProperty("AppVersion", "0.1"));
m.addData("log", read, "text/plain");
m.setFailSilently(true);
if(sync) {
NetworkManager.getInstance().addToQueueAndWait(m);
} else {
NetworkManager.getInstance().addToQueue(m);
}
} catch (Throwable ex) {
ex.printStackTrace();
}
}
/**
* Installs a log subclass that can replace the logging destination/behavior
*
* @param newInstance the new instance for the Log object
*/
public static void install(Log newInstance) {
instance = newInstance;
}
/**
* Default println method invokes the print instance method, uses DEBUG level
*
* @param text the text to print
*/
public static void p(String text) {
p(text, DEBUG);
}
/**
* Default println method invokes the print instance method, uses given level
*
* @param text the text to print
* @param level one of DEBUG, INFO, WARNING, ERROR
*/
public static void p(String text, int level) {
instance.print(text, level);
}
/**
* This method is a shorthand form for logThrowable
*
* @param t the exception
*/
public static void e(Throwable t) {
instance.logThrowable(t);
}
/**
* Logs an exception to the log, by default print is called with the exception
* details, on supported devices the stack trace is also physically written to
* the log
* @param t
*/
protected void logThrowable(Throwable t) {
if(t == null) {
p("Exception logging invoked with null exception...");
return;
}
print("Exception: " + t.getClass().getName() + " - " + t.getMessage(), ERROR);
Thread thr = Thread.currentThread();
if(thr instanceof CodenameOneThread && ((CodenameOneThread)thr).hasStackFrame()) {
print(((CodenameOneThread)thr).getStack(t), ERROR);
}
t.printStackTrace();
try {
synchronized(this) {
Writer w = getWriter();
Util.getImplementation().printStackTraceToStream(t, w);
w.flush();
}
} catch(IOException err) {
err.printStackTrace();
}
}
/**
* Default log implementation prints to the console and the file connector
* if applicable. Also prepends the thread information and time before
*
* @param text the text to print
* @param level one of DEBUG, INFO, WARNING, ERROR
*/
protected void print(String text, int level) {
if(!initialized) {
initialized = true;
try {
InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/cn1-version-numbers");
if(is != null) {
print("Codename One revisions: " + Util.readToString(is), INFO);
}
} catch(IOException err) {
// shouldn't happen...
err.printStackTrace();
}
}
if(this.level > level) {
return;
}
logDirty = true;
text = getThreadAndTimeStamp() + " - " + text;
Util.getImplementation().systemOut(text);
try {
synchronized(this) {
Writer w = getWriter();
w.write(text + "\n");
w.flush();
}
} catch(Throwable err) {
err.printStackTrace();
}
}
/**
* Default method for creating the output writer into which we write, this method
* creates a simple log file using the file connector
*
* @return writer object
* @throws IOException when thrown by the connector
*/
protected Writer createWriter() throws IOException {
try {
if(getFileURL() == null) {
return new OutputStreamWriter(Storage.getInstance().createOutputStream("CN1Log__$"));
}
if(FileSystemStorage.getInstance().exists(getFileURL())) {
return new OutputStreamWriter(FileSystemStorage.getInstance().openOutputStream(getFileURL(),
(int)FileSystemStorage.getInstance().getLength(getFileURL())));
} else {
return new OutputStreamWriter(FileSystemStorage.getInstance().openOutputStream(getFileURL()));
}
} catch(Exception err) {
setFileWriteEnabled(false);
// currently return a "dummy" writer so we won't fail on device
return new OutputStreamWriter(new ByteArrayOutputStream());
}
}
/**
* Deletes the current log file
*/
public static void deleteLog() {
if(instance.output != null) {
Util.cleanup(instance.output);
instance.output = null;
}
if(instance.getFileURL() == null) {
Storage.getInstance().deleteStorageFile("CN1Log__$");
} else {
if(FileSystemStorage.getInstance().exists(instance.getFileURL())) {
FileSystemStorage.getInstance().delete(instance.getFileURL());
}
}
}
private Writer getWriter() throws IOException {
if(output == null) {
output = createWriter();
}
return output;
}
/**
* Returns a simple string containing a timestamp and thread name.
*
* @return timestamp string for use in the log
*/
protected String getThreadAndTimeStamp() {
long time = System.currentTimeMillis() - zeroTime;
long milli = time % 1000;
time /= 1000;
long sec = time % 60;
time /= 60;
long min = time % 60;
time /= 60;
long hour = time % 60;
return "[" + Thread.currentThread().getName() + "] " + hour + ":" + min + ":" + sec + "," + milli;
}
/**
* Sets the logging level for printing log details, the lower the value
* the more verbose would the printouts be
*
* @param level one of DEBUG, INFO, WARNING, ERROR
*/
public static void setLevel(int level) {
instance.level = level;
}
/**
* Returns the logging level for printing log details, the lower the value
* the more verbose would the printouts be
*
* @return one of DEBUG, INFO, WARNING, ERROR
*/
public static int getLevel() {
return instance.level;
}
/**
* Returns the contents of the log as a single long string to be displayed by
* the application any way it sees fit
*
* @return string containing the whole log
* @deprecated this was practical in old J2ME devices but hasn't been maintained in ages, use sendLog() instead
*/
public static String getLogContent() {
try {
String text = "";
if(instance.isFileWriteEnabled()) {
if(instance.getFileURL() == null) {
instance.setFileURL("file:///" + FileSystemStorage.getInstance().getRoots()[0] + "/codenameOne.log");
}
Reader r = new InputStreamReader(FileSystemStorage.getInstance().openInputStream(instance.getFileURL()));
char[] buffer = new char[1024];
int size = r.read(buffer);
while(size > -1) {
text += new String(buffer, 0, size);
size = r.read(buffer);
}
r.close();
}
return text;
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
}
/**
* Places a form with the log as a TextArea on the screen, this method can
* be attached to appear at a given time or using a fixed global key. Using
* this method might cause a problem with further log output
* @deprecated this method is an outdated method that's no longer supported
*/
public static void showLog() {
try {
String text = getLogContent();
TextArea area = new TextArea(text, 5, 20);
Form f = new Form("Log");
f.setScrollable(false);
final Form current = Display.getInstance().getCurrent();
Command back = new Command("Back") {
public void actionPerformed(ActionEvent ev) {
current.show();
}
};
f.addCommand(back);
f.setBackCommand(back);
f.setLayout(new BorderLayout());
f.addComponent(BorderLayout.CENTER, area);
f.show();
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Returns the singleton instance of the log
*
* @return the singleton instance of the log
*/
public static Log getInstance() {
return instance;
}
/**
* Indicates whether GCF's file writing should be used to generate the log file
*
* @return the fileWriteEnabled
*/
public boolean isFileWriteEnabled() {
return fileWriteEnabled;
}
/**
* Indicates whether GCF's file writing should be used to generate the log file
*
* @param fileWriteEnabled the fileWriteEnabled to set
*/
public void setFileWriteEnabled(boolean fileWriteEnabled) {
this.fileWriteEnabled = fileWriteEnabled;
}
/**
* Indicates the URL where the log file is saved
*
* @return the fileURL
*/
public String getFileURL() {
return fileURL;
}
/**
* Indicates the URL where the log file is saved
*
* @param fileURL the fileURL to set
*/
public void setFileURL(String fileURL) {
if(!Objects.equals(this.fileURL, fileURL)) {
try {
this.fileURL = fileURL;
output = createWriter();
} catch(IOException ex) {
ex.printStackTrace();
}
}
}
/**
* Activates the filesystem tracking of file open/close operations
*/
public void trackFileSystem() {
Util.getImplementation().setLogListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
String s = (String)evt.getSource();
// don't log the creation of the log itself
if(output != null) {
p(s);
}
}
});
}
/**
* Binds pro based crash protection logic that will send out an email in case of an exception thrown on the EDT
*
* @param consumeError true will hide the error from the user, false will leave the builtin logic that defaults to
* showing an error dialog to the user
*/
public static void bindCrashProtection(final boolean consumeError) {
if(Display.getInstance().isSimulator()) {
return;
}
Display.getInstance().addEdtErrorHandler(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(consumeError) {
evt.consume();
}
p("Exception in " + Display.getInstance().getProperty("AppName", "app") + " version " + Display.getInstance().getProperty("AppVersion", "Unknown"));
p("OS " + Display.getInstance().getPlatformName());
p("Error " + evt.getSource());
if(Display.getInstance().getCurrent() != null) {
p("Current Form " + Display.getInstance().getCurrent().getName());
} else {
p("Before the first form!");
}
e((Throwable)evt.getSource());
if(getUniqueDeviceKey() != null) {
sendLog();
}
}
});
crashBound = true;
}
/**
* Returns true if the user bound crash protection
* @return true if crash protection is bound
*/
public static boolean isCrashBound() {
return crashBound;
}
}