What protocols are allowed in hrefs in Swing's HTMLEditorKit class? - java

I use an application (AppWorx! Someone please create this tag!) that allows documentation to be entered about scheduled jobs as html.
I've been trying to create on-call documentation that would have a link something like this:
1 (806) xxx - xxxx
The page is displayed inside the Java app itself, and any link to http:// is opened in the user's browser window. But a tel link like above causes a big error window to pop up that shows the following error:
java.net.MalformedURLException: For input string: "+1806xxxxxxx"
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at com.appworx.client.screen.modmgr.M$2.hyperlinkUpdate(NotesPanel.java:191)
at javax.swing.JEditorPane.fireHyperlinkUpdate(Unknown Source)
at javax.swing.text.html.HTMLEditorKit$LinkController.activateLink(Unknown Source)
at javax.swing.text.html.HTMLEditorKit$LinkController.mouseClicked(Unknown Source)
at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source)
Other protocols fail as well (except http). If I have a mailto: link, instead of getting the error as above, it takes me to the domain portion of the email address.
I believe that whatever version of this class that the app was compiled with is several (and maybe many) years old.
Can anyone tell me what the limitations of this class are, or if workarounds exist?
The documentation for Appworx suggests that even http links will not work unless the app is invoked from the jnlp (is this a sandbox thing somehow?). Though on that note, no one here starts the application any other way.

Can anyone tell me what the limitations of this class are?
To give you an idea of how outdated the EditorKit classes are, as of Java 7 HTMLEditorKit "supports HTML version 3.2 (with some extensions), and is migrating toward version 4.0". No surprise then that the URL class (responsible for the MalformedURLException in the trace you posted) supports just the basic protocols, some of which you mentioned above:
Http
Https
Ftp
File
Jar
Can anyone tell me if workarounds exist?
Well, you can get your hands dirty with the code (if you have access to it), use a custom protocol handler and register it. Luckily for you there is one already for the tel protocol courtesy of the J2ME Polish project:
package de.enough.polish.browser.protocols;
import java.io.IOException;
import javax.microedition.io.StreamConnection;
import javax.microedition.midlet.MIDlet;
import de.enough.polish.browser.ProtocolHandler;
/**
* Protocol handler to handle the <code>tel:</code> protocol. This class calls the given phonenumber on MIDP 2.0 phones.
* Example: <a href="tel:+441231234567#22">Call Me</a>
* Note that this handler requires MIDP 2.0 or higher.
* The tel protocol handler allows you to separate the phone number and the dialtone (dtmf) that should be send after
* establishing the phone call using the '#' sign.
*
* This protocol could actually be realized using the ExternalProtocolHandler as well, however in this
* way we can deal post dial tones (DTMF) in a better way - in the HTML code they just need to be
* separated from the phonenumber using a '#'.
*/
public class TelProtocolHandler
extends ProtocolHandler
{
private MIDlet midlet;
/**
* Creates an TellProtocolHandler object using the default "tel" protocol name.
*
* #param midlet the midlet object of the application
*/
public TelProtocolHandler(MIDlet midlet)
{
this( "tel", midlet );
}
/**
* Creates an TelProtocolHandler object using the specified protocol name.
*
* #param protocolName the name of the protocol to handle
* #param midlet the midlet object of the application
*/
public TelProtocolHandler(String protocolName, MIDlet midlet)
{
super( protocolName );
this.midlet = midlet;
}
/* (non-Javadoc)
* #see de.enough.polish.browser.ProtocolHandler#getConnection(java.lang.String)
*/
public StreamConnection getConnection(String url) throws IOException
{
this.midlet.platformRequest( "tel:" + extractMsisdn(url));
return null;
}
/**
* Strips the MSISDN part off an url.
* In contrast to other protocol handlers, the external protocol handler only uses a single colon to
* separate the external protocol from the folllowing protocol, e.g. external:http://www.j2mepolish.org
*
* #param url the url to remove the protocol from
*
* #return the host and part part of the given url
*/
protected String extractMsisdn(String url)
{
String msisdn = url.substring(this.protocolName.length() + 1);
String separator = null;
//#if polish.dtmf.separator:defined
//#= separator = "${polish.dtmf.separator}";
//# if (!separator.equals("#")) {
//# int pos = msisdn.indexOf('#');
//# if (pos != -1) {
//# msisdn = msisdn.substring(0, pos) + separator + msisdn.substring(pos + 1);
//# }
//# }
//#endif
return msisdn;
}
}
Hope that helps!

Related

Sample Code to Call Odata Service from Java for onprem SAP

/**
* Calls {#code GET API_SALES_ORDER_SRV/A_SalesOrder} through
* {#link FluentHelperRead} to get the SalesOrder events expanded to sales
* order items and filtered by {#code keys} list
*
* #param keys
* the list of sales orders IDs to be fetched
* #return the list of sales orders or an empty list if {#code keys} is empty
*
* #throws ODataException
* in case the request was not successful
* #throws IllegalArgumentException
* in case {#code keys} is null
*
* #see //ProcessSalesOrderService#getAllSalesOrder()
* #see <a href=
* "https://api.sap.com/shell/discover/contentpackage/SAPS4HANACloud/api/API_SALES_ORDER_SRV?resource=A_SalesOrder&operation=get_A_SalesOrder">SAP
* API Business Hub</a> for details of
* {#code GET API_SALES_ORDER_SRV/A_SalesOrder} endpoint
*/
public List<SalesOrderHeader> getByKeys(#NonNull Collection<String> keys) throws IllegalArgumentException, ODataException {
if (keys.size() == 0) {
return Collections.emptyList();
}
// create OData $filter with all keys
final ExpressionFluentHelper<SalesOrderHeader> filter = keys.stream()
.map(key -> SalesOrderHeader.SALES_ORDER.eq(key))
.reduce(ExpressionFluentHelper::or)
.get();
try {
HttpDestinationProperties destinationprop = null;
return salesOrderService.getAllSalesOrder()
.select(SalesOrderHeader.ALL_FIELDS, SalesOrderHeader.TO_ITEM)
.filter(filter)
.execute(destinationprop );
} catch (com.sap.cloud.sdk.odatav2.connectivity.ODataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I found the above sample code but since I am new to SAP and my system is an OnPrem version deployed on AWS. I am not sure how to pass the HttpDestinationProperties destinationprop
Further that method seems to be deprecated.
I am looking for some sample code to call the Sales order Odata Service using the code I generated using the instructions provided.
I generated the code using a maven plugin. https://sap.github.io/cloud-sdk/docs/java/features/odata/generate-typed-odata-v2-and-v4-client-for-java I am using the odata V2 Plugin
Usually you would use the SAP BTP Cloud Foundry Destination Service and Connectivity Service. Make sure to also have a Cloud Connector connected to your sub-account, it will act as reverse-proxy to the On-Premise system. You bind the destination service (e.g. plan lite) as well as the connectivity service (e.g. plan lite) to your application.
Once the prerequisites are met, you can use the SAP Cloud SDK code to resolve destinations:
// General API usage:
Destination destination = DestinationAccessor.getDestination("my-destination");
// Cast to HTTP destination:
HttpDestination httpDestination = destination.asHttp();
// Apply dedicated ERP logic for SAP S/4HANA
HttpDestination erpHttpDestination = httpDestination.decorate(DefaultErpHttpDestination::new);
(Of course you can boil it down to a one-liner.)
The OData call itself can be called like the following without try-catch:
return salesOrderService.getAllSalesOrder()
.select(SalesOrderHeader.ALL_FIELDS, SalesOrderHeader.TO_ITEM)
.filter(filter)
.executeRequest( erpHttpDestination );
That's it!
PS.: If you want to define your destination in static code, that would be possible with the DefaultErpHttpDestination.builder("http://your-proxy-host:44300") API. However this is obviously not best-practice.

Android Studio generate JavaDoc for AIDL

Given that AIDL contain interface definitions, it is important to incorporate them into our javadoc.
However, Android Studio completely refuses to see Javadoc comments added either to aidl files or those to be found in the java files generated from them.
This is what I have in my .aidl test file:
/**
* Displays a Toast Message containing the specified String.
* To be used for testing purpose only.
*
* #param message the Message to be displayed
* #return whether or not the Message could be shown
*/
boolean testMessage(String message);
and this is in the generated .java file:
/**
* Displays a Toast Message containing the specified String.
* To be used for testing purpose only.
*
* #param message the Message to be displayed
* #return whether or not the Message could be shown
*/
#Override public boolean testMessage(java.lang.String message) throws android.os.RemoteException
{
return false;
}
I can generate JavaDoc for the implementation file (e.g. AidlImpl.java in case of IAidl.aidl), but that would yield wrong references in the JavaDoc as the end user would have to use IAidl and not AidlImpl.
How's that supposed to work?
#edit: I ended up writing a wrapper class for the library which can contain javadoc comments the usual way.
Not exactly the most elegant solution, but reasonably straightforward.
Thanks for your attention!

start and stop stream consumption in php script from my java frontend

i am trying to make a project where the user inputs a couple of brands and receives feedback of their mentioned times in twitter.. so far i ve made/found/tweaked the basic frontend in java, the php scripts for consuming the twitter streaming api plus a database to save the incoming tweets,, the last two in a xaamp server locally. Its working perfectly but i must run the scripts manually through my browser.
what i need is
php scripts to run in the backround (as their creator insists )
start and stop scripts at will to change and renew requested keywords
and i need this to be done from my frontend.
i thought of this..
since in the first place i send user inputs to the scripts through my database (java arrayOfBrands => db table => php requests and gets a column as array ) i could do smth like a flag in mysql database changable by my frontend and critical in the execution of my script.
then i looked at this question
Starting / Stopping php script running in background from browser
but the guy here proposes to do it as a cronjob... the other guy who made the scripts says about a thousand times in the instructions "DONT DO IT AS A CRONJOB" but as a procedure in the backround... and they both seem good and pro(Adam Green 140dev and Aziz Saleh 1763 fame here ) and i dont know which way to go..
here is "my" code
<?php
/**
* get_tweets.php
* Collect tweets from the Twitter streaming API
* This must be run as a continuous background process
* Latest copy of this code: http://140dev.com/free-twitter-api-source-code-library/
* #author Adam Green <140dev#gmail.com>
* #license GNU Public License
* #version BETA 0.30
*/
ini_set('display_errors', true);
require_once('140dev_config.php');
require_once('brands.php');
require_once('../libraries/phirehose/Phirehose.php');
require_once('../libraries/phirehose/OauthPhirehose.php');
class Consumer extends OauthPhirehose
{
// A database connection is established at launch and kept open permanently
public $oDB;
public function db_connect() {
require_once('db_lib.php');
$this->oDB = new db;
}
// This function is called automatically by the Phirehose class
// when a new tweet is received with the JSON data in $status
public function enqueueStatus($status) {
$tweet_object = json_decode($status);
// Ignore tweets without a properly formed tweet id value
if (!(isset($tweet_object->id_str))) { return;}
$tweet_id = $tweet_object->id_str;
// If there's a ", ', :, or ; in object elements, serialize() gets corrupted
// You should also use base64_encode() before saving this
$raw_tweet = base64_encode(serialize($tweet_object));
$field_values = 'raw_tweet = "' . $raw_tweet . '", ' .
'tweet_id = ' . $tweet_id;
$this->oDB->insert('json_cache',$field_values);
}
}
// Open a persistent connection to the Twitter streaming API
$stream = new Consumer(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_FILTER);
// Establish a MySQL database connection
$stream->db_connect();
// The keywords for tweet collection are entered here as an array
// More keywords can be added as array elements
// For example: array('recipe','food','cook','restaurant','great meal')
$stream->setTrack($mybrands);
// Start collecting tweets
// Automatically call enqueueStatus($status) with each tweet's JSON data
$stream->consume();
this is the script i need to run/not run
plz help me in any way possible either code or advice or just a tip are valuable for me.
thanks in advance.

Eclipse Java Doc

I want to automatically generate a template in front of a method like this:
/**
*
* #param tabName
* #return
*/
Web searches have suggested SHIFT+ALT+J or /**. Indeed that has been working for many months. Suddenly today when I do a /** it generates only
/**
*
oddly enough, more towards the top of the class it works correctly. Or at least before most classes.
Here is my method def:
public String clickIt(Object search, Boolean exact, Object link)
but it does not work on other methods either. Any tips on figuring out the problem?
You can check the template used by Eclipse in the following menu item :
Window > Preferences then Java > Code Style > Code Templates
You can edit the Comments > Methods
The default value is :
/**
* ${tags}
*/

Detect mobile devices from user agent string [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I am looking for a way to analyze user agent strings to determine whether they were generated by mobile devices. This needs to be java-based and usable in large batch log file analysis on hadoop for generating statistics (i.e., a web service wouldn't be appropriate).
I have seen WURFL, but given that I just need a binary mobile/not mobile response, the license fee seems prohibitive.
So far I have been using UADetector, which is almost exactly what I need. However, I have encountered some limitations with it. In my testing, I have found many user agent strings that provide enough information to determine that the user agent is from a mobile device, but are reported as UNKNOWN by UADetector.
For example, poorly-standardized Android apps can send the UA string "Android". This is enough to know that it came from a mobile device, but UADetector reports this UserAgentType as UNKNOWN rather than MOBILE_BROWSER.
Apache Mobile Filter's Lite Device Detection does the right thing, but I need something I can use from Java.
Can anyone recommend a better solution?
I'm the founder and maintainer of the MobileESP project, a free open source cross-platform library for detecting mobile devices. It's still very much alive! :-)
www.mobileesp.org
MobileESP only gives binary "is mobile" responses. You can detect by platform like iOS, Android or Windows Phone, or by device category, like "iPhone Tier" smartphones vs. tablet. Be sure to take a quick review of the API page.
As you may know, useragent strings vary widely. If the browser shipped on the device, the manufacturer may customize it. For example, HTC often customizes the native Android browser's useragent string.
Google provides recommendations on how the OEM should customize the useragent. If the device should be considered a phone, then Google recommends including the word "mobile" element in the string. But if the device should be considered a tablet, then the string should not contain "mobile." Adherence to this recommendation varies widely, of course.
Third party browsers like Opera or Maxthon can put whatever they want to in the useragent string -- and do! Certain "new" browsers which shall remain nameless have been doing very poor jobs of putting the correct information in their useragent strings for each platform (e.g., Android vs. iOS versions). There's not much you can do unless you get a lot of traffic from these browsers and wish to invest in tracking their exact useragent values per platform and software rev.
Anyway, MobileESP was created with the vision of doing the detection on a page-by-page basis when the page is served. I purposefully wrote the code to be very easy to read and customize, too.
To do the batch processing, you might do something like this:
1.) In the constructor, comment out the initDeviceScan() method. You won't need this for bulk processing.
2.) Pass the UserAgent and an empty string in to the constructor (UAgentInfo()).
3.) Then run whatever detect methods you're interested in. Be thoughtful about the order in which you do them to save time, based on a scan of your users.
For example, if most of your users are on iPhone and that's one of the detection criteria you're interested in, then run that check first. If this example, you certainly wouldn't run the BlackBerry method first!
My contact info is in the source code and on the web site. Send me a note if you have any questions or run into any bugs. Definitely look around the MobileESP.org web site for some tips.
Best wishes on your project, Aniket!
Anthony
Another thread suggests using the following library:
https://github.com/ahand/mobileesp/blob/master/Java/UAgentInfo.java
which seems OK.
How to read the Apache Mobile Filter value in JSP (for Tomcat)?
Before in the httpd.conf file where you have to configure mod_jk you muse add this:
JkEnvVar AMF_IS_MOBILE undefined
The Java code is:
request.getAttribute("AMF_IS_MOBILE")
from: http://wiki.apachemobilefilter.org
51Degrees has a free open source Java API that allows you to run offline processing. You can access it from the GitHub Repository here. https://github.com/51Degrees/Java-Device-Detection.
As part of the API there is an offline processing example (code also shown below) this takes a CSV file of User-Agents and returns the required properties into an Output file. The following example just uses 3 of the properties within the data set, for a full list you can look at the dictionary here https://51degrees.com/resources/property-dictionary
// output file in current working directory
public String outputFilePath = "batch-processing-example-results.csv";
// pattern detection matching provider
private final Provider provider;
/**
* Initialises the device detection Provider with the included Lite data
* file. For more data see:
* <a href="https://51degrees.com/compare-data-options">compare data options
* </a>
*
* #throws IOException if there was a problem reading from the data file.
*/
public OfflineProcessingExample() throws IOException {
provider = new Provider(StreamFactory.create(
Shared.getLitePatternV32(), false));
}
/**
* Reads a CSV file containing User-Agents and adds the IsMobile,
* PlatformName and PlatformVersion information for the first 20 lines.
* For a full list of properties and the files they are available in please
* see: <a href="https://51degrees.com/resources/property-dictionary">
* Property Dictionary</a>
*
* #param inputFileName the CSV file to read from.
* #param outputFilename where to save the file with extra entries.
* #throws IOException if there was a problem reading from the data file.
*/
public void processCsv(String inputFileName, String outputFilename)
throws IOException {
BufferedReader bufferedReader =
new BufferedReader(new FileReader(inputFileName));
try {
FileWriter fileWriter = new FileWriter(outputFilename);
try {
// it's more efficient over the long haul to create a match
// once and reuse it in multiple matches
Match match = provider.createMatch();
// there are 20k lines in supplied file, we'll just do a couple
// of them!
for (int i = 0; i < 20; i++) {
// read next line
String userAgentString = bufferedReader.readLine();
// ask the provider to match the UA using match we created
provider.match(userAgentString, match);
// get some property values from the match
Values isMobile = match.getValues("IsMobile");
Values platformName = match.getValues("PlatformName");
Values platformVersion = match.getValues("PlatformVersion");
// write result to file
fileWriter.append("\"")
.append(userAgentString)
.append("\", ")
.append(getValueForDisplay(isMobile))
.append(", ")
.append(getValueForDisplay(platformName))
.append(", ")
.append(getValueForDisplay(platformVersion))
.append('\n')
.flush();
}
} finally {
fileWriter.close();
}
} finally {
bufferedReader.close();
}
}
/**
* Match values may be null. A helper method to get something displayable
* #param values a Values to render
* #return a non-null String
*/
protected String getValueForDisplay(Values values) {
return values == null ? "N/A": values.toString();
}
/**
* Closes the {#link fiftyone.mobile.detection.Dataset} by releasing data
* file readers and freeing the data file from locks. This method should
* only be used when the {#code Dataset} is no longer required, i.e. when
* device detection functionality is no longer required, or the data file
* needs to be freed.
*
* #throws IOException if there was a problem accessing the data file.
*/
#Override
public void close() throws IOException {
provider.dataSet.close();
}
/**
* Instantiates this class and starts
* {#link #processCsv(java.lang.String, java.lang.String)} with default
* parameters.
*
* #param args command line arguments.
* #throws IOException if there was a problem accessing the data file.
*/
public static void main(String[] args) throws IOException {
System.out.println("Starting Offline Processing Example");
OfflineProcessingExample offlineProcessingExample =
new OfflineProcessingExample();
try {
offlineProcessingExample.processCsv(Shared.getGoodUserAgentsFile(),
offlineProcessingExample.outputFilePath);
System.out.println("Output written to " +
offlineProcessingExample.outputFilePath);
} finally {
offlineProcessingExample.close();
}
}
Hope this helps.
Disclosure: I work at 51Degrees.
To detect iPhone, Android and other mobile devices in Java user-agent can be used. If you are using Spring you can customize the below code as per your need.
#Override
public ModelAndView redirectToAppstore(HttpServletRequest request) {
String userAgent = request.getHeader("user-agent").toLowerCase();
String iphoneStoreUrl = "IPONE_STORE_URL";
String androidStoreUrl = "ANDROID_STORE_URL";
if (userAgent.contains("iphone"))
return new ModelAndView("redirect:" + iphoneStoreUrl);
else if (userAgent.contains("android"))
return new ModelAndView("redirect:" + androidStoreUrl);
return new ModelAndView("redirect:/");
}

Categories

Resources