How to launch an interactive process in Windows on Java? - java

I need to run application in Windows with administrator rights on another user desktop.
I could do it with PsExec -i https://learn.microsoft.com/en-us/sysinternals/downloads/psexec but I want to do it in my Java application without additional exe files.
I run my code as administrator with elevated rights.
I found this article (it describes how to do it on .net):
https://www.codeproject.com/Articles/35773/Subverting-Vista-UAC-in-Both-32-and-64-bit-Archite
I translated code from article to Java but advapi32.CreateProcessAsUser returns false and I get 1314 error. Does anybody see what I missed in this code?
pom dependencies
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
my code
import com.sun.jna.Native;
import com.sun.jna.platform.win32.*;
public class TestWinRunSessionId {
public static void main(String[] args) {
System.out.println(System.getProperty("user.name"));
// id of the process which we use as a pointer to the target desktop (not administrator) where we will open new application from current user (administrator)
int procId = 18160;
WinNT.HANDLE hProcess = Kernel32.INSTANCE.OpenProcess(
WinNT.PROCESS_ALL_ACCESS,
false,
procId
);
System.out.println(hProcess);
WinNT.HANDLEByReference hPToken = new WinNT.HANDLEByReference();
boolean openProcessToken = Advapi32.INSTANCE.OpenProcessToken(
hProcess,
WinNT.TOKEN_DUPLICATE,
hPToken
);
if (!openProcessToken) {
Kernel32.INSTANCE.CloseHandle(hProcess);
throw new RuntimeException("1");
}
System.out.println(hPToken);
WinBase.SECURITY_ATTRIBUTES sa = new WinBase.SECURITY_ATTRIBUTES();
sa.dwLength = new WinDef.DWORD(sa.size());
WinNT.HANDLEByReference hUserTokenDup = new WinNT.HANDLEByReference();
boolean duplicateTokenEx = Advapi32.INSTANCE.DuplicateTokenEx(
hPToken.getValue(),
WinNT.TOKEN_ALL_ACCESS,
sa,
WinNT.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
WinNT.TOKEN_TYPE.TokenPrimary,
hUserTokenDup
);
if (!duplicateTokenEx) {
Kernel32.INSTANCE.CloseHandle(hProcess);
Kernel32.INSTANCE.CloseHandle(hPToken.getValue());
throw new RuntimeException("2");
}
System.out.println(hUserTokenDup);
WinBase.STARTUPINFO si = new WinBase.STARTUPINFO();
si.cb = new WinDef.DWORD(si.size());
si.lpDesktop = "winsta0\\default";
boolean result = Advapi32.INSTANCE.CreateProcessAsUser(
hUserTokenDup.getValue(), // client's access token
null, // file to execute
"C:\\Windows\\System32\\cmd.exe", // command line
sa, // pointer to process SECURITY_ATTRIBUTES
sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
WinBase.CREATE_UNICODE_ENVIRONMENT | WinBase.CREATE_NEW_CONSOLE, // creation flags ???
null, // pointer to new environment block ???
null, // name of current directory
si, // pointer to STARTUPINFO structure
new WinBase.PROCESS_INFORMATION() // receives information about new process
);
System.out.println("result: " + result);
System.out.println("error: " + Native.getLastError());
}
}

According to the CreateProcessAsUser.hToken:
A handle to the primary token that represents a user. The handle must
have the TOKEN_QUERY, TOKEN_DUPLICATE, and TOKEN_ASSIGN_PRIMARY access
rights.
So, you should OpenProcessToken with TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY.
The token duplicated does also not have enough permissions. You only specify the permissions of READ_CONTROL.
According to DuplicateTokenEx.dwDesiredAccess:
To request the same access rights as the existing token, specify zero.
So, you need to set securityLevel to zero.
Or juse specify TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY directly at DuplicateTokenEx
According to the document, CreateProcessAsUser requires two privileges:
SE_INCREASE_QUOTA_NAME
SE_ASSIGNPRIMARYTOKEN_NAME
Corresponding to Control Panel\All Control Panel Items\Administrative Tools\Local Security Policy\Security Settings\Local Policies\User Rights Assignment:
Adjust memory quotas for a process
Replace a process level token
EDIT:
Finally, I found a way to do(The error checking was removed and pay attention to the comments inside):
#include <windows.h>
#include <iostream>
#include <stdio.h>
#pragma comment(lib, "Advapi32.lib")
int main()
{
DWORD session_id = 0;
//Get a system token from System process id.
//Why? Because the following call: "SetTokenInformation" needs "the Act as part of the operating system" privilege, and local system has.
HANDLE hSys_Process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, 588);
HANDLE Sys_Token = 0;
OpenProcessToken(hSys_Process, TOKEN_QUERY| TOKEN_DUPLICATE, &Sys_Token);
CloseHandle(hSys_Process);
HANDLE Sys_Token_Dup;
if (!DuplicateTokenEx(Sys_Token, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &Sys_Token_Dup))
{
printf("DuplicateTokenEx ERROR: %d\n", GetLastError());
return FALSE;
}
//Enabling Privileges: "SE_INCREASE_QUOTA_NAME" and "SE_ASSIGNPRIMARYTOKEN_NAME" for CreateProcessAsUser().
TOKEN_PRIVILEGES *tokenPrivs=(TOKEN_PRIVILEGES*)malloc(sizeof(DWORD)+2* sizeof(LUID_AND_ATTRIBUTES));
tokenPrivs->PrivilegeCount = 2;
LookupPrivilegeValue(NULL, SE_INCREASE_QUOTA_NAME, &tokenPrivs->Privileges[0].Luid);
LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &tokenPrivs->Privileges[1].Luid);
tokenPrivs->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tokenPrivs->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(Sys_Token_Dup, FALSE, tokenPrivs, 0, (PTOKEN_PRIVILEGES)NULL, 0);
free(tokenPrivs);
//let the calling thread impersonate the local system, so that we can call SetTokenInformation().
ImpersonateLoggedOnUser(Sys_Token_Dup);
//get current process user token.
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId());
HANDLE Token = 0, hTokenDup = 0;
OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE, &Token);
CloseHandle(hProcess);
if (!DuplicateTokenEx(Token, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
{
printf("DuplicateTokenEx ERROR: %d\n", GetLastError());
return FALSE;
}
//set session id to token.
if (!SetTokenInformation(hTokenDup, TokenSessionId, &session_id, sizeof(DWORD)))
{
printf("SetTokenInformation Error === %d\n", GetLastError());
return FALSE;
}
//init struct.
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
char temp[] = "winsta0\\default";
char applicationName[] = "C:\\Windows\\System32\\cmd.exe";
si.lpDesktop = temp;
PROCESS_INFORMATION procInfo;
ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION));
//will return error 5 without CREATE_BREAKAWAY_FROM_JOB
//see https://blogs.msdn.microsoft.com/alejacma/2012/03/09/createprocessasuser-fails-with-error-5-access-denied-when-using-jobs/
int dwCreationFlags = CREATE_BREAKAWAY_FROM_JOB | CREATE_NEW_CONSOLE;
BOOL result = CreateProcessAsUser(
hTokenDup,
NULL, // file to execute
applicationName, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
dwCreationFlags, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&procInfo // receives information about new process
);
RevertToSelf();
return 0;
}

Related

java.nio.ByteBuffer wrap method partly working with sbt run

I have an issue where I read a bytestream from a big file ~ (100MB) and after some integers I get the value 0 (but only with sbt run ). When I hit the play button on IntelliJ I get the value I expected > 0.
My guess was that the environment is somehow different. But I could not spot the difference.
// DemoApp.scala
import java.nio.{ByteBuffer, ByteOrder}
object DemoApp extends App {
val inputStream = getClass.getResourceAsStream("/HandRanks.dat")
val handRanks = new Array[Byte](inputStream.available)
inputStream.read(handRanks)
inputStream.close()
def evalCard(value: Int) = {
val offset = value * 4
println("value: " + value)
println("offset: " + offset)
ByteBuffer.wrap(handRanks, offset, handRanks.length - offset).order(ByteOrder.LITTLE_ENDIAN).getInt
}
val cards: List[Int] = List(51, 45, 14, 2, 12, 28, 46)
def eval(cards: List[Int]): Unit = {
var p = 53
cards.foreach(card => {
println("p = " + evalCard(p))
p = evalCard(p + card)
})
println("result p: " + p);
}
eval(cards)
}
The HandRanks.dat can be found here: (I put it inside a directory called resources)
https://github.com/Robert-Nickel/scala-texas-holdem/blob/master/src/main/resources/HandRanks.dat
build.sbt is:
name := "LoadInts"
version := "0.1"
scalaVersion := "2.13.4"
On my windows machine I use sbt 1.4.6 with Oracle Java 11
You will see that the evalCard call will work 4 times but after the fifth time the return value is 0. It should be higher than 0, which it is when using IntelliJ's play button.
You are not reading a whole content. This
val handRanks = new Array[Byte](inputStream.available)
allocates only as much as InputStream buffer and then you read the amount in buffer with
inputStream.read(handRanks)
Depending of defaults you will process different amount but they will never be 100MB of data. For that you would have to read data into some structure in the loop (bad idea) or process it in chunks (with iterators, stream, etc).
import scala.util.Using
// Using will close the resource whether error happens or not
Using(getClass.getResourceAsStream("/HandRanks.dat")) { inputStream =>
def readChunk(): Option[Array[Byte]] = {
// can be done better, but that's not the point here
val buffer = new Array[Byte](inputStream.available)
val bytesRead = inputStream.read(buffer)
if (bytesRead >= 0) Some(buffer.take(bytesRead))
else None
}
#tailrec def process(): Unit = {
readChunk() match {
case Some(chunk) =>
// do something
process()
case None =>
// nothing to do - EOF reached
}
}
process()
}

Writing a WMI provider for a custom hardware in windows with JAVA

I have a custom hardware device which is connected to a windows computer. I want to provide the static information and dynamic data of this device to other services of the computer which query using WMI.
From my research I've found that I have to write a WMI provider. My current software application uses JPOS to interface the hardware. Hence I have to interface WMI to a Java application.
I've seen C# and c++ examples to achieve this task. My current understanding is to write a C++ wmi provider and use JNI to integrate to my current application. I've seen further examples where JNA is used to query using wmi. Yet my research did not yield any productive information on writing a provider with JNA.
Is writing a C++ and integrating through JNI the best way to handle this situation? Or is there any better solution?
Following are some hints on how I currently solved this issue for anyone who would like to try.
1. Creating a custom wmi class.
Windows wbemtest.exe tool is your friend. This tool can save your life as it can generate new wmi classes and edit them. When opened with administrative privileges, it can generate custom wmi classes, add properties and modify.
Alternatively a .mof file can be written to create a custom class. An example of a .mof file is as follows.
#pragma namespace("\\\\.\\Root\\Cimv2")
class MyTestClass
{
[Key] uint32 KeyProperty = 1;
string Version = "1.1.1";
};
Information on running this .mof file can be found here.
2. Adding properties
While webmtester and .mof method can be used to add properties there are powershell commandlets I found useful. A powerful set of powershell commandlets are here by Stephane van Gulick.
3. Retrieving properties programmatically
Example c++ program to retrieve properties programmatically is as below.
// PropertyRetrieve.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// WMI query to list all properties and values of the root/CIMV2:Detagger class.
// This C++ code was generated using the WMI Code Generator, Version 10.0.13.0
// https://www.robvanderwoude.com/wmigen.php
//
// The generated code was derived from sample code provided by Microsoft:
// https://msdn.microsoft.com/en-us/library/aa390423(v=vs.85).aspx
// The sample code was modified to display multiple properties.
// Most of the original comments from the sample code were left intact.
// Limited testing has been done in Microsoft Visual C++ 2010 Express Edition.
#define _WIN32_DCOM
#include <iostream>
#include <iomanip>
#include <string>
#include <comdef.h>
#include <Wbemidl.h>
using namespace std;
#pragma comment( lib, "wbemuuid.lib" )
HRESULT hr;
IWbemClassObject *pclsObj = NULL;
void DisplayProperty(LPCWSTR propertyname)
{
VARIANT vtProperty;
VariantInit(&vtProperty);
try
{
hr = pclsObj->Get(propertyname, 0, &vtProperty, 0, 0);
if (vtProperty.vt == VT_DISPATCH)
{
wcout << vtProperty.pdispVal;
}
else if (vtProperty.vt == VT_BSTR)
{
wcout << vtProperty.bstrVal;
}
else if (vtProperty.vt == VT_UI1)
{
wcout << vtProperty.uiVal;
}
else if (vtProperty.vt == VT_EMPTY)
{
wcout << L"[NULL]";
}
}
catch (...)
{
wcout.clear();
wcout << resetiosflags(std::ios::showbase);
}
VariantClear(&vtProperty);
}
int main(int argc, char **argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cerr << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cerr << "Failed to initialize security. Error code = 0x" << hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc
);
if (FAILED(hres))
{
cerr << "Failed to create IWbemLocator object. Err code = 0x" << hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\CIMV2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"root\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cerr << "Could not connect. Error code = 0x" << hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cerr << "Connected to root\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cerr << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT Name,TestValue,Version FROM Detagger"),
NULL,
NULL,
&pEnumerator
);
if (FAILED(hres))
{
cerr << "Query of Detagger class failed. Error code = 0x" << hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
ULONG uReturn = 0;
while (pEnumerator)
{
hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (hr != 0)
{
break;
}
wcout << "Name : ";
DisplayProperty((LPCWSTR)L"Name");
wcout << endl;
wcout << "TestValue : ";
DisplayProperty((LPCWSTR)L"TestValue");
wcout << endl;
wcout << "Version : ";
DisplayProperty((LPCWSTR)L"Version");
wcout << endl;
pclsObj->Release();
}
// Cleanup
// =======
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
cout << "Press anykey to exit.";
cin.ignore();
cin.get();
return 0; // Program successfully completed.
}
4. Modifying a property programmatically
An example c++ code to modify a property programmatically is as below. This option would require administrative privilege.
_variant_t var2(L"15");
IWbemClassObject *detaggerClass = NULL;
HRESULT dflkj = pSvc->GetObjectW(L"Detagger", 0, NULL, &detaggerClass, NULL);
IWbemClassObject *detaggerInstance = NULL;
dflkj = detaggerClass->SpawnInstance(0, &detaggerInstance);
detaggerInstance->Put(L"TestValue", 0, &var2, CIM_UINT8)
|| Fail("Put failed for 'TestValue'");
HRESULT er = pSvc->PutInstance(detaggerInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
Here I have modified the value of the unsigned int 8 variable called "TestValue"
5. Next step
The next option I would have is to interface the c++ application to the main Java application through JNA.

How to manipulate parameters sending to remote object in CORBA using interceptors

New to CORBA but could establish remote method invoking from a client to server. When using interceptors and try to encrypt parameters for the remote method, it throws below
Failed to initialise ORB: org.omg.CORBA.NO_RESOURCES: vmcid: OMG minor code: 1 completed: No org.omg.CORBA.NO_RESOURCES: vmcid: OMG minor code: 1completed: No at com.sun.corba.se.impl.logging.OMGSystemException.piOperationNotSupported1(Unknown Source)
at com.sun.corba.se.impl.logging.OMGSystemException.piOperationNotSupported1(Unknown Source)
at com.sun.corba.se.impl.interceptors.ClientRequestInfoImpl.arguments(Unknown Source)
at orb.CustomClientInterceptor.send_request(CustomClientInterceptor.java:23)
From Interceptors I'm trying to access arguments and encrypt them like below.
public void send_request( ClientRequestInfo ri )
{
System.out.println( ri.arguments() );
System.out.println( "Arguments.." );
logger( ri, "send_request" );
}
But cannot even access them, it throws above error. Intercepting methods are calling fine. Could you guide me with some code or a link.
Thanks in Advance
I found the answer and if someone hits this in future..
We cannot manipulate parameters in interceptors unless the call to CORBA object is either DII or DSI call. So first you need to make a call in either of these. I did it via DII. code is as follows.
//-ORBInitialPort 1050 -ORBInitialHost localhost
Properties p = new Properties();
p.put("org.omg.PortableInterceptor.ORBInitializerClass.orb.InterceptorORBInitializer", "");
//ORB orb = ORB.init(args, p);
String[] orbArgs = { "-ORBInitialHost", "localhost", "-ORBInitialPort", "1050" };
//NO_NEED ORB orb = ORB.init( orbArgs, null );
orb = ORB.init(orbArgs, p);
//objRef = orb.resolve_initial_references( "NameService" );
//ncRef = NamingContextExtHelper.narrow( objRef );
//DII Additional configs
org.omg.CORBA.Object ncRef = orb.resolve_initial_references ("NameService");
NamingContext nc = NamingContextHelper.narrow (ncRef);
NameComponent nComp = new NameComponent ("ABC", "");
NameComponent [] path = {nComp};
objRef = nc.resolve (path);
Then do the DII call, I have some mixed code here but you will understand what to do
NVList argList = orb.create_list (valueMap.size());
for (Map.Entry<String, String> entry : valueMap.entrySet()) {
Any argument = orb.create_any ();
argument.insert_string (entry.getValue());
argList.add_value (entry.getKey().toLowerCase(), argument, org.omg.CORBA.ARG_IN.value);
}
//Result
Any result = orb.create_any ();
result.insert_string( null );
NamedValue resultVal = orb.create_named_value ("result", result, org.omg.CORBA.ARG_OUT.value);
//Invoking Method
Request thisReq = objRef._create_request (null, methodName, argList, resultVal);
thisReq.invoke ();
//Extract Result
result = thisReq.result().value ();
Now from the interceptors you will need to filter the DII call only and then access the parameters like below.
public void send_request( ClientRequestInfo ri )
{
if(ri.operation().equals( "processPayment" ))
{
System.out.println( "################# CLIENT SIDE ###############" );
int count = 0;
for(Parameter param : ri.arguments())
{
System.out.println( "Arg : "+count );
System.out.println( param.argument.extract_string());
param.argument.insert_string( EncryptionDecryption.encrypt( param.argument.extract_string() ) );
count++;
}
}
System.out.println( "Arguments.." );
logger( ri, "send_request" );
}

How to pass java.util.Date to Java library with help of php-java bridge

Im using javabridge to connect php to jasper reports and Im trying to pass two parameters but I get warnings and errors
Warning: Unchecked exception detected: [[o:Response$UndeclaredThrowableErrorMarker]:"FATAL: Undeclared java.lang.RuntimeException detected. java.lang.Exception: CreateInstance failed: new java.util.Date((o:String)[o:String]). Cause: java.lang.IllegalArgumentException VM: 1.7.0_79#http://java.oracle.com/" at: #-10 java.util.Date.parse(Unknown Source) #-9 java.util.Date.<init>(Unknown Source) #-8 sun.reflect.GeneratedConstructorAccessor57.newInstance(Unknown Source) #-7 sun.reflect.DelegatingConstructorAccessor[...]/java/Java.inc(361): java_Arg->getResult(false) #2 http://localhost:8080/JavaBridgeTemplate/java/Java.inc(364): java_Client->getWrappedResult(false) #3 http://localhost:8080/JavaBridgeTemplate/java/Java.inc(536): java_Client->getInternalResult() #4 http://localhost:8080/JavaBridgeTemplate/java/Java.inc(1930): java_Client->createObject('java.util.Date', Array) #5 C:\wamp\www\advanced\backend\javabridge\generate.php(49): Java->Java('java.util.Date', '12/Feb/16') #6 {main}] in http://localhost:8080/JavaBridgeTemplate/java/Java.inc on line 202
Fatal error: Uncaught [[o:Exception]:"java.lang.Exception: Invoke failed: [[c:JasperFillManager]]->fillReport((o:JasperReport)[o:JasperReport], (i:Map)[o:HashMap], (i:Connection)[o:Connection]). Cause: net.sf.jasperreports.engine.JRException: Incompatible php.java.bridge.Response$UndeclaredThrowableErrorMarker value assigned to parameter FInicio in the Reubicados dataset. VM: 1.7.0_79#http://java.oracle.com/" at: #-16 net.sf.jasperreports.engine.fill.JRFillDataset.setParameter(JRFillDataset.java:903) #-15 net.sf.jasperreports.engine.fill.JRFillDataset.setFillParameterValues(JRFillDataset.java:642) #-14 net.sf.jasperreports.engine.fill.JRFillDataset.setParameterValues(JRFillDataset.java:585) #-13 net.sf.jasperreports.engine.fill.JRBaseFiller.setParameters(JRBaseFiller.java:1280) #-12 net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:901) #-11 net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:845) #-10 net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:58) #-9 net.sf.jas in http://localhost:8080/JavaBridgeTemplate/java/Java.inc on line 195
The problem is when it tries to create java.util.Date instance. HereĀ“s php file:
<?php
require_once("http://localhost:8080/JavaBridgeTemplate/java/Java.inc");
try {
$Param1 = date('d/M/y', strtotime($_POST['FInicio']));
$Param2 = date('d/M/y', strtotime($_POST['FFin']));
$jasperxml = new java("net.sf.jasperreports.engine.xml.JRXmlLoader");
$jasperDesign = $jasperxml->load(realpath("Reubicados.jrxml"));
$query = new java("net.sf.jasperreports.engine.design.JRDesignQuery");
$jasperDesign->setQuery($query);
$compileManager = new JavaClass("net.sf.jasperreports.engine.JasperCompileManager");
$report = $compileManager->compileReport($jasperDesign); } catch (JavaException $ex) {
echo $ex; }
$fillManager = new JavaClass("net.sf.jasperreports.engine.JasperFillManager"); //aqui se pasan los parametros (Fecha Inicio y Fecha Fin)
$params = new Java("java.util.HashMap");
$date=new Java('java.util.Date',$Param1);
$date1=new Java('java.util.Date',$Param2);
$params->put("FInicio",$date);
$params->put("FFin",$date1);
$class = new JavaClass("java.lang.Class"); $class->forName("com.mysql.jdbc.Driver"); $driverManager = new JavaClass("java.sql.DriverManager");
//db username and password
$conn = $driverManager->getConnection("jdbc:mysql://localhost/viajestrafico?zeroDateTimeBehavior=convertToNull", "root", "root"); $jasperPrint = $fillManager->fillReport($report, $params, $conn);
$exporter = new java("net.sf.jasperreports.engine.JRExporter");
And sql query in ireports:
SELECT
ayudante_situacion_laboral.`FechaInicio` AS ayudante_situacion_laboral_FechaInicio,
ayudante_situacion_laboral.`FechaFin` AS ayudante_situacion_laboral_FechaFin,
ayudante_situacion_laboral.`Cant_Horas` AS ayudante_situacion_laboral_Cant_Horas,
ayudante_situacion_laboral.`Descripcion` AS ayudante_situacion_laboral_Descripcion,
ayudante.`Registro` AS ayudante_Registro,
ayudante.`Nombre` AS ayudante_Nombre,
situacion_laboral.`Estado` AS situacion_laboral_Estado
FROM
`ayudante` ayudante INNER JOIN `ayudante_situacion_laboral` ayudante_situacion_laboral ON ayudante.`Ayudante_ID` = ayudante_situacion_laboral.`AyudanteAyudante_ID`
INNER JOIN `situacion_laboral` situacion_laboral ON ayudante_situacion_laboral.`Situacion_LaboralSitL_ID` = situacion_laboral.`SitL_ID`
WHERE
situacion_laboral.Estado = 'Reubicado' and $P{FInicio}<= ayudante_situacion_laboral.`FechaInicio` and $P{FFin}>=ayudante_situacion_laboral.`FechaFin`
UNION
SELECT
chofer_situacion_laboral.`FechaInicio` AS chofer_situacion_laboral_FechaInicio,
chofer_situacion_laboral.`FechaFin` AS chofer_situacion_laboral_FechaFin,
chofer_situacion_laboral.`Cant_Horas` AS chofer_situacion_laboral_Cant_Horas,
chofer_situacion_laboral.`Descripcion` AS chofer_situacion_laboral_Descripcion,
chofer.`Registro` AS chofer_Registro,
chofer.`Nombre` AS chofer_Nombre,
situacion_laboral.`Estado` AS situacion_laboral_Estado
FROM
`chofer` chofer INNER JOIN `chofer_situacion_laboral` chofer_situacion_laboral ON chofer.`Chofer_ID` = chofer_situacion_laboral.`ChoferChofer_ID`
INNER JOIN `situacion_laboral` situacion_laboral ON chofer_situacion_laboral.`Situacion_LaboralSitL_ID` = situacion_laboral.`SitL_ID`
WHERE
(situacion_laboral.Estado = 'Reubicado' and $P{FInicio}<= chofer_situacion_laboral.`FechaInicio` and $P{FFin}>=chofer_situacion_laboral.`FechaFin`)
Looking to your error message, the java.util.Date cannot be created with '12/Feb/16':
java_Client->createObject('java.util.Date', Array)
#5 C:\wamp\www\advanced\backend\javabridge\generate.php(49):
Java->Java('java.util.Date', '12/Feb/16') #6 {main}] in
If you want to instanciate a java date object, use the java.util.Date(long date) constructor which accepts a timestamp expressed in milliseconds :
<?php
$startDate = $_POST['FInicio']; // better to filter this :)
$Param1 = strtotime($startDate) * 1000; // to get milliseconds
if ($Param1 == 0) {
throw new Exception("FInicio date parameter could not be parsed");
}
// ...
$javaDate = new Java('java.util.Date',$Param1); // This is a java date
Your $date parameter should now be a valid java.util.Date object.
You can test it :
$simpleDateFormat = new Java("java.text.SimpleDateFormat", 'yyyy-MM-dd');
echo $simpleDateFormat->format($javaDate);
// should print your date in Y-m-d format
Alternatively, you can parse the date in Java through the java.text.SimpleDateFormatter object:
$date = '2016-12-21';
$simpleDateFormat = new Java("java.text.SimpleDateFormat", 'yyyy-MM-dd');
$javaDate = $simpleDateFormat->parse($date); // This is a Java date
Both approaches works...
JasperReport issue with date
Not exactly linked to your question, but if you want to use your Date as a query parameter you should use the java.sql.Date(long date) object instead of java.util.Date... Here's a little dirty snippet to summarize changes:
// php
$sqlDate = new Java('java.sql.Date', strtotime($_POST['FInicio']) * 1000));
$params->put('FInicio', $sqlDate);
// in your report header (.jrxml):
<parameter name="FInicio" class="java.sql.Date">
// in your report query (.jrxml):
$P{FInicio} <= chofer_situacion_laboral.`FechaInicio`
You can also have a look to the soluble-japha javabridge client (refactored Java.inc client), the syntax differs a bit but there's a documentation about dates that might reveal useful.
It was simple, just a problem I had from the beginning in php code.
$query = new java("net.sf.jasperreports.engine.design.JRDesignQuery");
$jasperDesign->setQuery($query);
This code was preventing xrml query from executing, because it was creating a query object empty.

How to use ogr2ogr in java gdal

I would like to code ogr2ogr -f "GeoJSON" destination.geojson source.geojson -s_srs EPSG:3068 -t_srs EPSG:4326 in java-gdal. I tried to understand how it should work by looking at this example but since ogr2ogr has many many uses I could not quite figure what is relevant for me. Here is my attempt:
public static void ogr2ogr(String name, String sourceSRS, String destSRS) {
ogr.RegisterAll();
String pszFormat = "GeoJSON";
DataSource poDS = ogr.Open(name + "_" + sourceSRS+".geojson", false);
/* -------------------------------------------------------------------- */
/* Try opening the output datasource as an existing, writable */
/* -------------------------------------------------------------------- */
DataSource poODS = ogr.Open(name + "_" + destSRS+".geojson", 0);
Driver poDriver = ogr.GetDriverByName(pszFormat);
SpatialReference poOutputSRS = new SpatialReference();
poOutputSRS.SetFromUserInput( destSRS );
SpatialReference poSourceSRS = new SpatialReference();
poSourceSRS.SetFromUserInput( sourceSRS );
CoordinateTransformation poCT = CoordinateTransformation.CreateCoordinateTransformation( poSourceSRS, poOutputSRS );
Layer poDstLayer = poODS.GetLayerByName("bla");
Feature poDstFeature = new Feature( poDstLayer.GetLayerDefn() );
Geometry poDstGeometry = poDstFeature.GetGeometryRef();
int eErr = poDstGeometry.Transform( poCT );
poDstLayer.CommitTransaction();
poDstGeometry.AssignSpatialReference(poOutputSRS);
}
I get this exception at poOutputSRS.SetFromUserInput( destSRS ); (that is line 99):
ERROR 3: Cannot open file 'C:\Users\Users\Desktop\test\target_EPSG4326.geojson'
Exception in thread "main" java.lang.RuntimeException: OGR Error: Corrupt data
at org.gdal.osr.osrJNI.SpatialReference_SetFromUserInput(Native Method)
at org.gdal.osr.SpatialReference.SetFromUserInput(SpatialReference.java:455)
at wmsRasterToGeojsonVector.GdalJava.ogr2ogr(GdalJava.java:99)
at wmsRasterToGeojsonVector.GdalJava.main(GdalJava.java:30)

Categories

Resources