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 5 years ago.
Improve this question
I have several finished, older PHP projects with a lot of includes that I would like to document in javadoc/phpDocumentor style.
While working through each file manually and being forced to do a code review alongside the documenting would be the best thing, I am, simply out of time constraints, interested in tools to help me automate the task as much as possible.
The tool I am thinking about would ideally have the following features:
Parse a PHP project tree and tell me where there are undocumented files, classes, and functions/methods (i.e. elements missing the appropriate docblock comment)
Provide a method to half-way easily add the missing docblocks by creating the empty structures and, ideally, opening the file in an editor (internal or external I don't care) so I can put in the description.
Optional:
Automatic recognition of parameter types, return values and such. But that's not really required.
The language in question is PHP, though I could imagine that a C/Java tool might be able to handle PHP files after some tweaking.
Thanks for your great input!
I think PHP_Codesniffer can indicate when there is no docblock -- see the examples of reports on this page (quoting one of those) :
--------------------------------------------------------------------------------
FOUND 5 ERROR(S) AND 1 WARNING(S) AFFECTING 5 LINE(S)
--------------------------------------------------------------------------------
2 | ERROR | Missing file doc comment
20 | ERROR | PHP keywords must be lowercase; expected "false" but found
| | "FALSE"
47 | ERROR | Line not indented correctly; expected 4 spaces but found 1
47 | WARNING | Equals sign not aligned with surrounding assignments
51 | ERROR | Missing function doc comment
88 | ERROR | Line not indented correctly; expected 9 spaces but found 6
--------------------------------------------------------------------------------
I suppose you could use PHP_Codesniffer to at least get a list of all files/classes/methods that don't have a documentation; from what I remember, it can generate XML as output, which would be easier to parse using some automated tool -- that could be the first step of some docblock-generator ;-)
Also, if you are using phpDocumentor to generate the documentation, can this one not report errors for missing blocks ?
After a couple of tests, it can -- for instance, running it on a class-file with not much documentation, with the --undocumentedelements option, such as this :
phpdoc --filename MyClass.php --target doc --undocumentedelements
Gives this in the middle of the output :
Reading file /home/squale/developpement/tests/temp/test-phpdoc/MyClass.php -- Parsing file
WARNING in MyClass.php on line 2: Class "MyClass" has no Class-level DocBlock.
WARNING in MyClass.php on line 2: no #package tag was used in a DocBlock for class MyClass
WARNING in MyClass.php on line 5: Method "__construct" has no method-level DocBlock.
WARNING in MyClass.php on line 16: File "/home/squale/developpement/tests/temp/test-phpdoc/MyClass.php" has no page-level DocBlock, use #package in the first DocBlock to create one
done
But, here, too, even if it's useful as a reporting tool, it's not that helpful when it comes to generating the missing docblocks...
Now, I don't know of any tool that will pre-generate the missing docblocks for you : I generally use PHP_Codesniffer and/or phpDocumentor in my continuous integration mecanism, it reports missing docblocks, and, then, each developper adds what is missing, from his IDE...
... Which works pretty fine : there is generally not more than a couple of missing docblocks every day, so the task can be done by hand (and Eclipse PDT provides a feature to pre-generate the docblock for a method, when you are editing a specific file/method).
Appart from that, I don't really know any fully-automated tool to generate docblocks... But I'm pretty sure we could manage to create an interesting tool, using either :
The Reflection API
token_get_all to parse the source of a PHP file.
After a bit more searching, though, I found this blog-post (it's in french -- maybe some people here will be able to understand) : Ajout automatique de Tags phpDoc à l'aide de PHP_Beautifier.
Possible translation of the title : "Automatically adding phpDoc tags, using PHP_Beautifier"
The idea is actually not bad :
The PHP_Beautifier tool is pretty nice and powerful, when it comes to formating some PHP code that's not well formated
I've used it many times for code that I couldn't even read ^^
And it can be extended, using what it calls "filters".
see PHP_Beautifier_Filter for a list of provided filters
The idea that's used in the blog-post I linked to is to :
create a new PHP_Beautifier filter, that will detect the following tokens :
T_CLASS
T_FUNCTION
T_INTERFACE
And add a "draft" doc-block just before them, if there is not already one
To run the tool on some MyClass.php file, I've had to first install PHP_Beautifier :
pear install --alldeps Php_Beautifier-beta
Then, download the filter to the directory I was working in (could have put it in the default directory, of course) :
wget http://fxnion.free.fr/downloads/phpDoc.filter.phpcs
cp phpDoc.filter.phpcs phpDoc.filter.php
And, after that, I created a new beautifier-1.php script (Based on what's proposed in the blog-post I linked to, once again), which will :
Load the content of my MyClass.php file
Instanciate PHP_Beautifier
Add some filters to beautify the code
Add the phpDoc filter we just downloaded
Beautify the source of our file, and echo it to the standard output.
The code of the beautifier-1.php script will like this :
(Once again, the biggest part is a copy-paste from the blog-post ; I only translated the comments, and changed a couple of small things)
require_once 'PHP/Beautifier.php';
// Load the content of my source-file, with missing docblocks
$sourcecode = file_get_contents('MyClass.php');
$oToken = new PHP_Beautifier();
// The phpDoc.filter.php file is not in the default directory,
// but in the "current" one => we need to add it to the list of
// directories that PHP_Beautifier will search in for filters
$oToken->addFilterDirectory(dirname(__FILE__));
// Adding some nice filters, to format the code
$oToken->addFilter('ArrayNested');
$oToken->addFilter('Lowercase');
$oToken->addFilter('IndentStyles', array('style'=>'k&r'));
// Adding the phpDoc filter, asking it to add a license
// at the beginning of the file
$oToken->addFilter('phpDoc', array('license'=>'php'));
// The code is in $sourceCode
// We could also have used the setInputFile method,
// instead of having the code in a variable
$oToken->setInputString($sourcecode);
$oToken->process();
// And here we get the result, all clean !
echo $oToken->get();
Note that I also had to path two small things in phpDoc.filter.php, to avoid a warning and a notice...
The corresponding patch can be downloaded there : http://extern.pascal-martin.fr/so/phpDoc.filter-pmn.patch
Now, if we run that beautifier-1.php script :
$ php ./beautifier-1.php
With a MyClass.php file that initialy contains this code :
class MyClass {
public function __construct($myString, $myInt) {
//
}
/**
* Method with some comment
* #param array $params blah blah
*/
public function doSomething(array $params = array()) {
// ...
}
protected $_myVar;
}
Here's the kind of result we get -- once our file is Beautified :
<?php
/**
*
* PHP version 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license#php.net so we can mail you a copy immediately.
* #category PHP
* #package
* #subpackage Filter
* #author FirstName LastName <mail>
* #copyright 2009 FirstName LastName
* #link
* #license http://www.php.net/license/3_0.txt PHP License 3.0
* #version CVS: $Id:$
*/
/**
* #todo Description of class MyClass
* #author
* #version
* #package
* #subpackage
* #category
* #link
*/
class MyClass {
/**
* #todo Description of function __construct
* #param $myString
* #param $myInt
* #return
*/
public function __construct($myString, $myInt) {
//
}
/**
* Method with some comment
* #param array $params blah blah
*/
public function doSomething(array $params = array()) {
// ...
}
protected $_myVar;
}
We can note :
The license block at the beginning of the file
The docblock that's been added on the MyClass class
The docblock that's been added on the __construct method
The docblock on the doSomething was already present in our code : it's not been removed.
There are some #todo tags ^^
Now, it's not perfect, of course :
It doesn't document all the stuff we could want it too
For instance, here, it didn't document the protected $_myVar
It doesn't enhance existing docblocks
And it doesn't open the file in any graphical editor
But that would be much harder, I guess...
But I'm pretty sure that this idea could be used as a starting point to something a lot more interesting :
About the stuff that doesn't get documented : adding new tags that will be recognized should not be too hard
You just have to add them to a list at the beginning of the filter
Enhancing existing docblocks might be harder, I have to admit
A nice thing is this could be fully-automated
Using Eclipse PDT, maybe this could be set as an External Tool, so we can at least launch it from our IDE ?
Since PHPCS was already mentioned, I throw in the Reflection API to check for missing DocBlocks. The article linked below is a short tutorial on how you could approach your problem:
http://www.phpriot.com/articles/reflection-api
There is also a PEAR Package PHP_DocBlockGenerator that can Create the file Page block and the DocBlocks for includes, global variables, functions, parameters, classes, constants, properties and methods (and other things).
php-tracer-weaver can instrument code and generate docblocks with the parameter types, deducted through runtime analysis.
You can use the Code Sniffer for PHP to test your code against a predefined set of coding guidelines. It will also check for missing docblocks and generate a report you can use to identify the files.
The 1.4.x versions of phpDocumentor have the -ue option (--undocumentedelements) [1], which will cause undocumented elements to be listed as warnings on the errors.html page that it generates during its doc run.
Further, PHP_DocBlockGenerator [2] from PEAR looks like it can generate missing docblocks for you.
[1] -- http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html#using.command-line.undocumentedelements
[2] -- http://pear.php.net/package/PHP_DocBlockGenerator
We use codesniffer for this functionality at work, using standard PEAR or Zend standards. It will not allow you to edit the files on the fly, but will definitely give you a list, with lines and description of what kind of docblock is missing.
HTH,
Jc
No idea if it's any help, but if Codesniffer can point out the functions/methods, then a decent PHP IDE (I offer PHPEd) can easily inspect and scaffold the PHPDoc comments for each function.
Simply type /** above each function and press ENTER, and PHPEd will auto-complete the code with #param1, #param1, #return, etc. filled out correctly, ready for your extra descriptions. Here's the first one I tried in order to provide an example:
/**
* put your comment here...
*
* #param mixed $url
* #param mixed $method
* #param mixed $timeout
* #param mixed $vars
* #param mixed $allow_redirects
* #return mixed
*/
public static function curl_get_file_contents($url, $method = 'get', $timeout = 30, $vars = array(), $allow_redirects = true)
This is easily tweaked to:
/**
* Retrieves a file using the cURL extension
*
* #param string $url
* #param string $method
* #param int $timeout
* #param array $vars parameters to pass to cURL
* #param int $allow_redirects boolean choice to follow any redirects $url serves up
* #return mixed
*/
public static function curl_get_file_contents($url, $method = 'get', $timeout = 30, $vars = array(), $allow_redirects = true)
Not exactly an automated solution, but quick enough for me as a lazy developer :)
You want to actually automate the problem of filling in the "javadoc" type data?
The DMS Software Reengineering Toolkit could be configured to do this.
It parses source text just like compilers do, builds internal compiler structures, lets you implement arbitrary analyses, make modification to those structures, and then regenerate ("prettyprint") the source text changed according to the structure changes. It even preserves comments and formatting of the original text; you can of course insert additional comments and they will appear and this seems to be your primary goal. DMS does this for many languages, including PHP
What you would want to do is parse each PHP file, locate every class/method, generate the "javadoc" comments that should be that entity (difference for classes and methods, right?) and then check that corresponding comments were actually present in the compiler structures. If not, simply insert them. PrettyPrint the final result.
Because it has access to the compiler structures that represent the code, it shouldn't be difficult to generate parameter and return info, as you suggested. What it can't do, of course, is generate comments about intendend purpose; but it could generate a placeholder for you to fill in later.
I had to do a large batch of automation of docblock fixing recently, mostly based on the correct answer above kwith some context-specific changes. It's a hack, but I'm linking back here in case it's useful to anyone else in the future. Essentially, it does basic parsing on comment block tokens within PHP Beautifier.
https://gist.github.com/israelshirk/408f2656100196e73367
Related
Today I came across an obfuscated class (well a lot of obfuscated classes in a jar) and I do not have a clue on how this kind of obfuscation is done.
An example:
protected void a(ChannelHandlerContext ☃, ByteBuf ☃, ByteBuf ☃)
throws Exception
{
int ☃ = ☃.readableBytes();
if (☃ < this.c)
{
☃.b(0);
☃.writeBytes(☃);
}
else
{
byte[] ☃ = new byte[☃];
☃.readBytes(☃);
☃.b(☃.length);
this.b.setInput(☃, 0, ☃);
this.b.finish();
while (!this.b.finished())
{
int ☃ = this.b.deflate(this.a);
☃.writeBytes(this.a, 0, ☃);
}
this.b.reset();
}
}
}
As you see above, all the parameter variables are a snow-man. How can this be undone? Also how is it done in the first place; how is the JVM able to "process" those and execute the code without any problem?
To clarify, I am not going to use this code, it is just for educational purposes. I am taking the Computer Science course at school so since we are learning Java and talking of limitations such as decompilations. I am interested in learning more, so I decided to have a look into bigger projects especially servers. This piece of code is pulled out of the Spigot server for Minecraft (A game) that is a fork of Bukkit server for Minecraft that was supposed to be open source.
First of all, you should note that it is the parameters which have this unicode and not the methods. Why is this important?
Parameters do not need to have names specified, as they are mostly indexed by a number reference. However it can be specified and I assume that most java runtimes do in fact not check this name as it is not needed for execution.
In the opposite, class names, method names, and field names are however needed.
About you mentioning Spigot, Spigot is indeed open source. However you most likely decompiled a class which is originally from the original Mojang Minecraft server, which is not open source and is indeed obfuscated.
Edit: In the case you want to investigate these classes, I recently found a tool called Bytecode Viewer, which is available at https://github.com/Konloch/bytecode-viewer
This tool has multiple decompilers as well as some options to view a more bytecode like version of the class file.
An example of a function I found contains the following bytecode data:
<localVar:index=1 , name=☃ , desc=D, sig=null, start=L1, end=L2>
<localVar:index=3 , name=☃ , desc=D, sig=null, start=L1, end=L2>
<localVar:index=5 , name=☃ , desc=D, sig=null, start=L1, end=L2>
Indeed as is visible, the unicode name has been set the same, but it does not matter as in the end the indexes (1,3,5) are used to reference these variables.
protected void a(ChannelHandlerContext ☃, ByteBuf ☃, ByteBuf ☃)
This isn't valid. You cannot have multiple parameters with the same name. It could be that you are not reading the unicode text with the right text format.
Your Text editor is showing the value of the unicode character.
I just tested on eclipse and names with unicode characters are acceptable.
public String publicationXmlUrl(int \u9090currentPage) {
But writing with values are not:
public String publicationXmlUrl(int ♥currentPage) {
I'm trying to display something like:
Welcome John Doe
In my Liferay Velocity Based Template which is used in a WebContent on Liferay 6.2 GA1 CE
So far the code i have is the following:
#set ($userLS = $portal.getClass().forName('com.liferay.portal.service.UserLocalServiceUtil'))
#set ($userId = $getterUtil.getLong($request.get("theme-display").get("user-id")))
#set ($user = $userLS.getUserById($userId))
<div class="user-welcome">
#if($user.isMale())
<span class="welcome-msg">Bienvenido</span><br>
#else
<span class="welcome-msg">Bienvenida</span><br>
#end
<span class="username">$user.getFullName() $user.getLastName()</span>
</div>
The errors i'm having are:
$user.isMale() always returns false
in my span.username the output is the code itself. It doesn't print the value.
Thanks in advance
Edit: The answer to your question upfront, I'll leave the rest of the explanation below:
If you want to access the current user, you can get it from $permissionChecker. So just replace your first three lines with this:
#set( $user = $permissionChecker.getUser() )
Here's my old explanation on why the technique used in your question didn't work:
Check $userLS.getClass().getName(): It's already not resolving properly. The reason most likely is this setting:
#
# Set a comma delimited list of Java classes the Velocity engine cannot have
# access to.
#
velocity.engine.restricted.classes=\
java.lang.Class,\
java.lang.ClassLoader,\
java.lang.Thread
Check this Wiki article to learn about serviceLocator, but be aware that it is - for good reasons - also unavailable from templates.
#
# Set a comma delimited list of variables the Velocity engine cannot
# have access to. This will affect Dynamic Data List templates, Journal
# templates, and Portlet Display templates.
#
velocity.engine.restricted.variables=serviceLocator
If you're the only one writing templates (or if you trust everyone doing so) it's fine to change this configuration in portal-ext.properties: Configure serviceLocator to not be restricted, then call
#set($userLocalService = $serviceLocator.findExceptionSafeService(
"com.liferay.portal.service.UserLocalService"))
On the positive side: This will ease error handling, as the exceptionSafeService will transparently ignore all exceptions - velocity can't handle them and without this behaviour you'd see no result (and no hint for the error message) at all, should an exception occur ever.
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:/");
}
I have a very long SQL statement inside of a Java String. In eclipse, how can I easily get the SQL statement's text without the Java String syntax? I've been manually removing it, but in IntelliJ Idea, it's possible for one to get the text without having to do any manual formatting work to remove the Java String syntax (such as " and + characters). Does Eclipse have a similar feature?
As an added bonus, I would ask if it were also possible to get the string with the newlines put in place as it was formatted in the IDE, even if no \n characters were present in the string itself.
Depending on your SQL client, it could have this feature.
I know that TOAD has this feature built-in. I also remember Squirrel having it.
So when pasted into the SQL editor of TOAD, the code is automatically extracted from the Java string syntax. I remember that it also worked with constructs like StringBuffer/StringBuilder.
See: http://dev.toadformysql.com/webhelp/Content/Editor/Convert_SQL_Embedded_SQL.htm
Or you can create a simple regexp working for your sample code, for example this jsfiddle.
It works with a regex for sql like:
"select something \r\n" +
" from dual " +
"where 1 = 1\r\n";
The jsfiddle should output
select something
from dual
where 1=1
Still it is not beautifully formatted (even if with the <pre> tag it should preserve spaces), but your SQL IDE should help you with that, no?
(we are using Kepler)
This StringUtils plugin looks quite good: http://marketplace.eclipse.org/content/stringutils-plugin (click screenshots).
not found in Eclipse market place dialog for install
downloaded the master ZIP from their GIT repo, but did not go on in favor of solution 5.
Together with the Java Multi-Line String Editor plugin it will be really easy to write/read/debug such SQL statements: https://marketplace.eclipse.org/content/java-multi-line-string-editor
not found in Eclipse market place dialog for install
Another nice solution seems the Multiline annotation where one can maintain the string in the javadoc (which will be transformed in a properly formatted string on compile time): https://github.com/benelog/multiline
externalizing large Strings/SQLs in separate *.sql files (and reading them e.g. from the classpath) would be the 2nd best option if it is appropriate:
https://stackoverflow.com/a/878648/1915920
https://stackoverflow.com/a/878776/1915920
The best solution for us was to use Groovy (THE "Java scripting extension") alongside our Java code:
you need to install the Groovy plugin https://github.com/groovy/groovy-eclipse/wiki
just saying New -> Groovy Class added the Groovy Nature automatically to our project and after that, you can implement your SQLs as constants or enums similar to this:
supports almost everything (even between the Java-Groovy barriers) that Java (Editors) support:
code highlighting
refactoring (renaming), but only from within Groovy file
auto-completion/CTRL+rightclick-navigation
Javadoc hinting
src/my/pkg/SQLs.groovy:
package my.pkg
class SQLs {
/** comment X */
static final String SEL_X = ```
select
bla,
foo
from
bar
where
x in (1,2,3)
```
}
src/my/pkg/SqlExec.java:
// ...
stmt.executeQuery( SQLs.getSEL_X() ) ; /* Groovy auto-created this getSEL_X()
interface method transparently/auto-
suggested, but the "comment X" is not
hinted */
and more proper for our use case was to use the SQLs as an enum:
enum SQLs {
/** comment X */
SEL_X(```
select
...
x in (1,2,3)
```)
String sql
SQLs( String sql ) { this.sql = sql }
}
which can be accessed within src/my/pkg/SqlExec.java as this:
// the JavaDoc comment "comment X" works and the getSql() is transparently
// auto-generated by Groovy
stmt.executeQuery( SQLs.SEL_X.getSql() ) ;
And more sugar with debugging it all within Eclipse with DTP :-)
=> so debugging these SQLs will be as easy as:
SQLs.groovy file => Open with ... => Other => SQL Editor (from the very nice Eclipse Data Tools Platform (DTP) plugin: https://eclipse.org/datatools/)
you can always switch between editors as you like (Eclipse remembers the last used per file)
selecting the proper connection for this file from the custom pre-configured db connections (must be open/connected, if not done already)
marking to-be-debugged SQL + ALT+X
debug query results as tabbed or text-only results ...
My requirement is simple. At the beginning of each file there should be a block comment like this:
/*
* This file was last modified by {username} at {date} and has revision number {revisionnumber}
*/
I want to populate the {username}, {date} and {revisionnumber} with the appropriate content from SVN.
How can I achieve this with NetBeans and Subversion? I have searched a lot but I can't find exactly what I need.
I looked at this question and got some useful information. It is not exactly duplicate because I am working with NetBeans but the idea is the same. This is my header:
/*
* $LastChangedDate$
* $LastChangedRevision$
*/
Then I go to Team > Subversion > Svn properties and add svn:keywords as property name and LastChangedDate LastChangedRevision as property value.
And when I commit from NetBeans it looks like this:
/*
* $LastChangedDate: 2012-02-13 17:38:57 +0200 (Пн, 13 II 2012) $
* $LastChangedRevision: 27 $
*/
Thanks all for the support! I will accept my answer because other answers do not include the NetBeans information. Nevertheless I give +1 to the other answers.
As this data only exists after the file was committed it should be set by SVN itself, not a client program. (And client-side processing tends to get disabled or not configured at all.) This means there is no simple template/substitute like you want, because then after the first replacement the template variables would be lost.
You can find information abut SVN's keyword substitution here. Then things like $Rev$ can be replaced by $Rev: 12 $.
You can do this with The SubWCRev Program.
SubWCRev is Windows console program which can be used to read the
status of a Subversion working copy and optionally perform keyword
substitution in a template file. This is often used as part of the
build process as a means of incorporating working copy information
into the object you are building. Typically it might be used to
include the revision number in an “About” box.
This is typically done during the build process.
If you use Linux, you can find a Linux binary here. If you wish, you could also write your own using the output of svn log.
I followed Petar Minchev's suggestions, only I put the $LastChangedRevision$ tag not in a comment block but embedded it in a string. Now it is available to programmatically display the revision number in a Help -> About dialog.
String build = "$LastChangedRevision$";
I can later display the revision value in the about dialog using a String that has all of the fluff trimmed off.
String version = build.replace("$LastChangedRevision:", "").replace("$", "").trim();
I recommend a slightly different approach.
Put the following header at the top of your source files.
/*
* This file was last modified by {username} at {date} and has revision number {revisionnumber}
*/
Then add a shell script like this
post update, checkout script
USERNAME=# // use svnversion to get username
DATE=# // use svnversion to get revisio nnumber
sed -e "s#{username}#${USERNAME}#" -e "s#{date}#${DATE}#" ${SOURCE_CONTROL_FILE} > ${SOURCE_FILE}
pre commit script
cat standard_header.txt > ${SOURCE_CONTROL_FILE}
tail --lines $((${LENGTH}-4)) ${SOURCE_FILE} >> ${SOURCE_CONTROL_FILE}